From b8561cdd295181e017da719c981134cc0a5344aa Mon Sep 17 00:00:00 2001 From: Waldemar Kornewald Date: Sat, 6 Sep 2003 17:13:51 +0000 Subject: [PATCH] Added PPPLCPExtension (allows additional codes for LCP). Added Control() op codes for report enabling/disabling. Fixed memory leaks in StateMachine and LCP (packets were not freed). Some minor changes. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4514 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/tests/kits/net/ppp/headers/KPPPDefs.h | 4 +- src/tests/kits/net/ppp/headers/KPPPDevice.h | 5 +- .../kits/net/ppp/headers/KPPPEncapsulator.h | 4 - src/tests/kits/net/ppp/headers/KPPPLCP.h | 10 +- .../kits/net/ppp/headers/KPPPLCPExtension.h | 60 +++++++++ .../kits/net/ppp/headers/KPPPOptionHandler.h | 5 +- .../kits/net/ppp/headers/KPPPReportDefs.h | 21 --- .../kits/net/ppp/headers/KPPPReportManager.h | 5 +- .../kits/net/ppp/headers/KPPPStateMachine.h | 8 +- src/tests/kits/net/ppp/headers/PPPControl.h | 46 +++---- src/tests/kits/net/ppp/headers/PPPDefs.h | 2 +- .../kits/net/ppp/headers/PPPReportDefs.h | 11 +- src/tests/kits/net/ppp/src/Jamfile | 1 + src/tests/kits/net/ppp/src/KPPPDevice.cpp | 2 +- src/tests/kits/net/ppp/src/KPPPInterface.cpp | 17 +++ src/tests/kits/net/ppp/src/KPPPLCP.cpp | 70 +++++++++- .../kits/net/ppp/src/KPPPLCPExtension.cpp | 84 ++++++++++++ .../kits/net/ppp/src/KPPPOptionHandler.cpp | 10 +- .../kits/net/ppp/src/KPPPReportManager.cpp | 4 +- .../kits/net/ppp/src/KPPPStateMachine.cpp | 120 ++++++++++++++---- 20 files changed, 379 insertions(+), 110 deletions(-) create mode 100644 src/tests/kits/net/ppp/headers/KPPPLCPExtension.h delete mode 100644 src/tests/kits/net/ppp/headers/KPPPReportDefs.h create mode 100644 src/tests/kits/net/ppp/src/KPPPLCPExtension.cpp diff --git a/src/tests/kits/net/ppp/headers/KPPPDefs.h b/src/tests/kits/net/ppp/headers/KPPPDefs.h index 32998072e3..e7c3fd54fa 100644 --- a/src/tests/kits/net/ppp/headers/KPPPDefs.h +++ b/src/tests/kits/net/ppp/headers/KPPPDefs.h @@ -49,9 +49,9 @@ enum PPP_EVENT { PPP_RXR_EVENT }; -// LCP protocol types as defined in RFC 1661 +// LCP protocol codes as defined in RFC 1661 // ToDo: add LCP extensions -enum PPP_LCP_TYPE { +enum PPP_LCP_CODE { PPP_CONFIGURE_REQUEST = 1, PPP_CONFIGURE_ACK = 2, PPP_CONFIGURE_NAK = 3, diff --git a/src/tests/kits/net/ppp/headers/KPPPDevice.h b/src/tests/kits/net/ppp/headers/KPPPDevice.h index 71fb8bf23b..8cd6a601c8 100644 --- a/src/tests/kits/net/ppp/headers/KPPPDevice.h +++ b/src/tests/kits/net/ppp/headers/KPPPDevice.h @@ -8,8 +8,6 @@ #ifndef _K_PPP_DEVICE__H #define _K_PPP_DEVICE__H -#include - #include #ifndef _K_PPP_INTERFACE__H @@ -78,14 +76,13 @@ class PPPDevice { void DownEvent(); protected: + uint32 fMTU; bool fIsUp; private: char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; PPPInterface& fInterface; driver_parameter *fSettings; - - uint32 fMTU; }; diff --git a/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h b/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h index c71ddfd1a6..a1693e2e2f 100644 --- a/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h +++ b/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h @@ -8,12 +8,8 @@ #ifndef _K_PPP_ENCAPSULATOR__H #define _K_PPP_ENCAPSULATOR__H -#include - #include -class PPPInterface; - #ifndef _K_PPP_INTERFACE__H #include #endif diff --git a/src/tests/kits/net/ppp/headers/KPPPLCP.h b/src/tests/kits/net/ppp/headers/KPPPLCP.h index a426ee856a..b9a15648e4 100644 --- a/src/tests/kits/net/ppp/headers/KPPPLCP.h +++ b/src/tests/kits/net/ppp/headers/KPPPLCP.h @@ -23,6 +23,7 @@ #endif class PPPEncapsulator; +class PPPLCPExtension; class PPPOptionHandler; @@ -30,7 +31,7 @@ typedef struct ppp_lcp_packet { uint8 code; uint8 id; uint16 length; - int8 data[0]; + uint8 data[0]; } ppp_lcp_packet; @@ -56,6 +57,12 @@ class PPPLCP : public PPPProtocol { { return fOptionHandlers.CountItems(); } PPPOptionHandler *OptionHandlerAt(int32 index) const; + bool AddLCPExtension(PPPLCPExtension *extension); + bool RemoveLCPExtension(PPPLCPExtension *extension); + int32 CountLCPExtensions() const + { return fLCPExtensions.CountItems(); } + PPPLCPExtension *LCPExtensionAt(int32 index) const; + PPPEncapsulator *Target() const { return fTarget; } void SetTarget(PPPEncapsulator *target) @@ -78,6 +85,7 @@ class PPPLCP : public PPPProtocol { PPPStateMachine& fStateMachine; List fOptionHandlers; + List fLCPExtensions; PPPEncapsulator *fTarget; }; diff --git a/src/tests/kits/net/ppp/headers/KPPPLCPExtension.h b/src/tests/kits/net/ppp/headers/KPPPLCPExtension.h new file mode 100644 index 0000000000..deea93cb9d --- /dev/null +++ b/src/tests/kits/net/ppp/headers/KPPPLCPExtension.h @@ -0,0 +1,60 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +// +// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de +//--------------------------------------------------------------------- + +#ifndef __K_PPP_LCP_EXTENSION__H +#define __K_PPP_LCP_EXTENSION__H + +#include + +#ifndef _K_PPP_INTERFACE__H +#include +#endif + + +class PPPLCPExtension { + public: + PPPLCPExtension(const char *name, uint8 code, PPPInterface& interface, + driver_parameter *settings); + virtual ~PPPLCPExtension(); + + virtual status_t InitCheck() const; + + const char *Name() const + { return fName; } + + PPPInterface& Interface() const + { return fInterface; } + driver_parameter *Settings() const + { return fSettings; } + + void SetEnabled(bool enabled = true) + { fEnabled = enabled; } + bool IsEnabled() const + { return fEnabled; } + + uint8 Code() const + { return fCode; } + + virtual status_t Control(uint32 op, void *data, size_t length); + + virtual void Reset(); + + virtual status_t Receive(struct mbuf *packet, uint8 code) = 0; + + virtual void Pulse(); + + private: + char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; + PPPInterface& fInterface; + driver_parameter *fSettings; + uint8 fCode; + + bool fEnabled; +}; + + +#endif diff --git a/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h b/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h index cea3b2dcac..8e63f93653 100644 --- a/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h +++ b/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h @@ -8,8 +8,6 @@ #ifndef _K_PPP_OPTION_HANDLER__H #define _K_PPP_OPTION_HANDLER__H -#include - #include #ifndef _K_PPP_INTERFACE__H @@ -35,7 +33,8 @@ class PPPOptionHandler { driver_parameter *Settings() const { return fSettings; } - void SetEnabled(bool enabled = true); + void SetEnabled(bool enabled = true) + { fEnabled = enabled; } bool IsEnabled() const { return fEnabled; } diff --git a/src/tests/kits/net/ppp/headers/KPPPReportDefs.h b/src/tests/kits/net/ppp/headers/KPPPReportDefs.h deleted file mode 100644 index b1c3821042..0000000000 --- a/src/tests/kits/net/ppp/headers/KPPPReportDefs.h +++ /dev/null @@ -1,21 +0,0 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the OpenBeOS license. -// -// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de -//--------------------------------------------------------------------- - -#ifndef _K_PPP_REPORT_DEFS__H -#define _K_PPP_REPORT_DEFS__H - -#include - - -typedef struct ppp_report_request { - thread_id thread; - int32 type; - int32 flags; -} ppp_report_request; - - -#endif diff --git a/src/tests/kits/net/ppp/headers/KPPPReportManager.h b/src/tests/kits/net/ppp/headers/KPPPReportManager.h index 9a04f0a408..b0cddbe131 100644 --- a/src/tests/kits/net/ppp/headers/KPPPReportManager.h +++ b/src/tests/kits/net/ppp/headers/KPPPReportManager.h @@ -10,7 +10,8 @@ #include -#include +#include +#include #include @@ -23,7 +24,7 @@ class PPPReportManager { ~PPPReportManager(); void EnableReports(PPP_REPORT_TYPE type, thread_id thread, - int32 flags = PPP_NO_REPORT_FLAGS); + int32 flags = PPP_NO_FLAGS); void DisableReports(PPP_REPORT_TYPE type, thread_id thread); bool DoesReport(PPP_REPORT_TYPE type, thread_id thread); bool Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length); diff --git a/src/tests/kits/net/ppp/headers/KPPPStateMachine.h b/src/tests/kits/net/ppp/headers/KPPPStateMachine.h index 2be9d7a445..ed293b9821 100644 --- a/src/tests/kits/net/ppp/headers/KPPPStateMachine.h +++ b/src/tests/kits/net/ppp/headers/KPPPStateMachine.h @@ -11,7 +11,6 @@ #include class PPPEncapsulator; -class PPPInterface; class PPPProtocol; #ifndef _K_PPP_INTERFACE__H @@ -106,7 +105,8 @@ class PPPStateMachine { void RCNEvent(struct mbuf *packet); void RTREvent(struct mbuf *packet); void RTAEvent(struct mbuf *packet); - void RUCEvent(struct mbuf *packet, uint16 protocol, uint8 type = PPP_PROTOCOL_REJECT); + void RUCEvent(struct mbuf *packet, uint16 protocol, + uint8 code = PPP_PROTOCOL_REJECT); void RXJGoodEvent(struct mbuf *packet); void RXJBadEvent(struct mbuf *packet); void RXREvent(struct mbuf *packet); @@ -128,8 +128,8 @@ class PPPStateMachine { void SendConfigureAck(struct mbuf *packet); void SendConfigureNak(struct mbuf *packet); void SendTerminateRequest(); - void SendTerminateAck(struct mbuf *request); - void SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type); + void SendTerminateAck(struct mbuf *request = NULL); + void SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 code); void SendEchoReply(struct mbuf *request); void BringHandlersUp(); diff --git a/src/tests/kits/net/ppp/headers/PPPControl.h b/src/tests/kits/net/ppp/headers/PPPControl.h index dfdb06d4f2..c388ca56fa 100644 --- a/src/tests/kits/net/ppp/headers/PPPControl.h +++ b/src/tests/kits/net/ppp/headers/PPPControl.h @@ -22,7 +22,6 @@ #define PPP_OPTION_HANDLER_OPS_START PPP_OPS_START + 5 * PPP_RESERVE_OPS_COUNT #define PPP_LCP_EXTENSION_OPS_START PPP_OPS_START + 6 * PPP_RESERVE_OPS_COUNT #define PPP_COMMON_OPS_START PPP_OPS_START + 10 * PPP_RESERVE_OPS_COUNT -#define PPP_COMMON_PROTO_ENCAPS_OPS_START PPP_OPS_START + 11 * PPP_RESERVE_OPS_COUNT #define PPP_USER_OPS_START PPP_OPS_START + 32 * PPP_RESERVE_OPS_COUNT @@ -34,6 +33,11 @@ enum PPP_CONTROL_OPS { PPPC_SET_DIAL_ON_DEMAND, PPPC_SET_AUTO_REDIAL, + // these control ops use the ppp_report_request structure + PPPC_ENABLE_INTERFACE_REPORTS, + PPPC_DISABLE_INTERFACE_REPORTS, + // flags are not used for this control op + // handler access PPPC_CONTROL_DEVICE, PPPC_CONTROL_PROTOCOL, @@ -49,31 +53,13 @@ enum PPP_CONTROL_OPS { PPPC_SET_MTU, // ----------------------------------------------------- - // ----------------------------------------------------- - // PPPProtocol - // ----------------------------------------------------- - - // ----------------------------------------------------- - // PPPEncapsulator - // ----------------------------------------------------- - - // ----------------------------------------------------- - // PPPOptionHandler - PPPC_GET_OPTION_HANDLER_INFO = PPP_OPTION_HANDLER_OPS_START, - // ----------------------------------------------------- - - // ----------------------------------------------------- - // PPPLCPExtension - // ----------------------------------------------------- - // ----------------------------------------------------- // Common/mixed ops PPPC_GET_HANDLER_INFO = PPP_COMMON_OPS_START, + // PPPProtocol and PPPEncapsulator PPPC_SET_ENABLED, - // ----------------------------------------------------- - - // ----------------------------------------------------- - // PPPProtocol and PPPEncapsulator + PPPC_GET_SIMPLE_HANDLER_INFO, + // PPPOptionHandler and PPPLCPExtension // ----------------------------------------------------- PPP_CONTROL_OPS_END = B_DEVICE_OP_CODES_END + 0xFFFF @@ -166,17 +152,19 @@ typedef struct ppp_handler_info_t { } ppp_handler_info_t; -typedef struct ppp_option_handler_info { +typedef struct ppp_simple_handler_info { char name[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; const driver_parameter *settings; - bool isEnabled; -} ppp_option_handler_info; -typedef struct ppp_option_handler_info_t { - ppp_option_handler_info info; - uint8 _reserved_[_PPP_INFO_T_SIZE_ - sizeof(ppp_option_handler_info)]; -} ppp_option_handler_info_t; + + uint8 code; + // only PPPLCPExtension +} ppp_simple_handler_info; +typedef struct ppp_simple_handler_info_t { + ppp_simple_handler_info info; + uint8 _reserved_[_PPP_INFO_T_SIZE_ - sizeof(ppp_simple_handler_info)]; +} ppp_simple_handler_info_t; #endif diff --git a/src/tests/kits/net/ppp/headers/PPPDefs.h b/src/tests/kits/net/ppp/headers/PPPDefs.h index 6984e41819..c68d952d61 100644 --- a/src/tests/kits/net/ppp/headers/PPPDefs.h +++ b/src/tests/kits/net/ppp/headers/PPPDefs.h @@ -8,7 +8,7 @@ #ifndef _PPP_DEFS__H #define _PPP_DEFS__H -#include +#include // various constants diff --git a/src/tests/kits/net/ppp/headers/PPPReportDefs.h b/src/tests/kits/net/ppp/headers/PPPReportDefs.h index 1f4cc7dec2..a719a46906 100644 --- a/src/tests/kits/net/ppp/headers/PPPReportDefs.h +++ b/src/tests/kits/net/ppp/headers/PPPReportDefs.h @@ -18,7 +18,6 @@ // report flags enum PPP_REPORT_FLAGS { - PPP_NO_REPORT_FLAGS = 0, PPP_WAIT_FOR_REPLY = 0x1, PPP_REMOVE_AFTER_REPORT = 0x2, PPP_NO_REPLY_TIMEOUT = 0x4 @@ -27,8 +26,11 @@ enum PPP_REPORT_FLAGS { // report types // the first 16 report types are reserved for the interface manager enum PPP_REPORT_TYPE { + PPP_ALL_REPORTS = -1, + // used only when disabling reports PPP_DESTRUCTION_REPORT = 16, // the interface is being destroyed (no code is needed) + // this report is sent even if it was not requested PPP_CONNECTION_REPORT = 17 }; @@ -54,4 +56,11 @@ typedef struct ppp_report_packet { } ppp_report_packet; +typedef struct ppp_report_request { + PPP_REPORT_TYPE type; + thread_id thread; + int32 flags; +} ppp_report_request; + + #endif diff --git a/src/tests/kits/net/ppp/src/Jamfile b/src/tests/kits/net/ppp/src/Jamfile index 2394551b26..5822d8b342 100644 --- a/src/tests/kits/net/ppp/src/Jamfile +++ b/src/tests/kits/net/ppp/src/Jamfile @@ -13,6 +13,7 @@ R5KernelStaticLibrary kernelppp : KPPPEncapsulator.cpp KPPPInterface.cpp KPPPLCP.cpp + KPPPLCPExtension.cpp KPPPOptionHandler.cpp KPPPProtocol.cpp KPPPReportManager.cpp diff --git a/src/tests/kits/net/ppp/src/KPPPDevice.cpp b/src/tests/kits/net/ppp/src/KPPPDevice.cpp index 83b44cf545..97dc6eea2d 100644 --- a/src/tests/kits/net/ppp/src/KPPPDevice.cpp +++ b/src/tests/kits/net/ppp/src/KPPPDevice.cpp @@ -15,7 +15,7 @@ PPPDevice::PPPDevice(const char *name, PPPInterface& interface, driver_parameter *settings) - : fInterface(interface), fSettings(settings), fMTU(1500) + : fMTU(1500), fIsUp(false), fInterface(interface), fSettings(settings) { if(name) { strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); diff --git a/src/tests/kits/net/ppp/src/KPPPInterface.cpp b/src/tests/kits/net/ppp/src/KPPPInterface.cpp index 8336f0637e..bea6306edf 100644 --- a/src/tests/kits/net/ppp/src/KPPPInterface.cpp +++ b/src/tests/kits/net/ppp/src/KPPPInterface.cpp @@ -283,6 +283,23 @@ PPPInterface::Control(uint32 op, void *data, size_t length) SetAutoRedial(*((uint32*)data)); break; + case PPPC_ENABLE_INTERFACE_REPORTS: { + if(length < sizeof(ppp_report_request) || !data) + return B_ERROR; + + ppp_report_request *request = (ppp_report_request*) data; + ReportManager().EnableReports(request->type, request->thread, + request->flags); + } break; + + case PPPC_DISABLE_INTERFACE_REPORTS: { + if(length < sizeof(ppp_report_request) || !data) + return B_ERROR; + + ppp_report_request *request = (ppp_report_request*) data; + ReportManager().DisableReports(request->type, request->thread); + } break; + case PPPC_CONTROL_DEVICE: { if(length < sizeof(ppp_control_info) || !data) return B_ERROR; diff --git a/src/tests/kits/net/ppp/src/KPPPLCP.cpp b/src/tests/kits/net/ppp/src/KPPPLCP.cpp index 0d642fb259..5b996d0622 100644 --- a/src/tests/kits/net/ppp/src/KPPPLCP.cpp +++ b/src/tests/kits/net/ppp/src/KPPPLCP.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -19,9 +20,6 @@ #define PPP_PROTOCOL_OVERHEAD 2 -// TODO: -// - add LCP extension handlers - PPPLCP::PPPLCP(PPPInterface& interface) : PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL, @@ -80,6 +78,48 @@ PPPLCP::OptionHandlerAt(int32 index) const return handler; } + +bool +PPPLCP::AddLCPExtension(PPPLCPExtension *extension) +{ + if(!extension) + return false; + + LockerHelper locker(StateMachine().Locker()); + + if(Phase() != PPP_DOWN_PHASE) + return false; + // a running connection may not change + + return fLCPExtensions.AddItem(extension); +} + + +bool +PPPLCP::RemoveLCPExtension(PPPLCPExtension *extension) +{ + LockerHelper locker(StateMachine().Locker()); + + if(Phase() != PPP_DOWN_PHASE) + return false; + // a running connection may not change + + return fLCPExtensions.RemoveItem(extension); +} + + +PPPLCPExtension* +PPPLCP::LCPExtensionAt(int32 index) const +{ + PPPLCPExtension *extension = fLCPExtensions.ItemAt(index); + + if(extension == fLCPExtensions.GetDefaultItem()) + return NULL; + + return extension; +} + + uint32 PPPLCP::AdditionalOverhead() const { @@ -163,11 +203,28 @@ PPPLCP::Receive(struct mbuf *packet, uint16 protocol) case PPP_ECHO_REPLY: case PPP_DISCARD_REQUEST: + m_freem(packet); // do nothing break; - default: - StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT); + default: { + status_t result = PPP_UNHANDLED; + + // try to find LCP extensions that can handle this code + PPPLCPExtension *extension; + for(int32 index = 0; index < CountLCPExtensions(); index++) { + extension = LCPExtensionAt(index); + if(extension->IsEnabled() && extension->Code() == data->code) + result = extension->Receive(packet, data->code); + } + + if(result == PPP_UNHANDLED) { + StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT); + return PPP_REJECTED; + } + + return result; + } } return B_OK; @@ -178,4 +235,7 @@ void PPPLCP::Pulse() { StateMachine().TimerEvent(); + + for(int32 index = 0; index < CountLCPExtensions(); index++) + LCPExtensionAt(index)->Pulse(); } diff --git a/src/tests/kits/net/ppp/src/KPPPLCPExtension.cpp b/src/tests/kits/net/ppp/src/KPPPLCPExtension.cpp new file mode 100644 index 0000000000..989e210534 --- /dev/null +++ b/src/tests/kits/net/ppp/src/KPPPLCPExtension.cpp @@ -0,0 +1,84 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +// +// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de +//--------------------------------------------------------------------- + +#include + +#include + + +PPPLCPExtension::PPPLCPExtension(const char *name, uint8 code, PPPInterface& interface, + driver_parameter *settings) + : fInterface(interface), fSettings(settings), fCode(code), fEnabled(true) +{ + if(name) { + strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); + fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0; + } else + strcpy(fName, "???"); + + interface.LCP().AddLCPExtension(this); +} + + +PPPLCPExtension::~PPPLCPExtension() +{ + Interface().LCP().RemoveLCPExtension(this); +} + + +status_t +PPPLCPExtension::InitCheck() const +{ + if(!Settings()) + return B_ERROR; + + return B_OK; +} + + +status_t +PPPLCPExtension::Control(uint32 op, void *data, size_t length) +{ + switch(op) { + case PPPC_GET_SIMPLE_HANDLER_INFO: { + if(length < sizeof(ppp_simple_handler_info_t) || !data) + return B_ERROR; + + ppp_simple_handler_info *info = (ppp_simple_handler_info*) data; + memset(info, 0, sizeof(ppp_simple_handler_info_t)); + strcpy(info->name, Name()); + info->settings = Settings(); + info->isEnabled = IsEnabled(); + } break; + + case PPPC_SET_ENABLED: + if(length < sizeof(uint32) || !data) + return B_ERROR; + + SetEnabled(*((uint32*)data)); + break; + + default: + return PPP_UNHANDLED; + } + + return B_OK; +} + + +void +PPPLCPExtension::Reset() +{ + // do nothing by default +} + + +void +PPPLCPExtension::Pulse() +{ + // do nothing by default +} diff --git a/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp b/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp index f93111b181..69473cea28 100644 --- a/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp +++ b/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp @@ -12,7 +12,7 @@ PPPOptionHandler::PPPOptionHandler(const char *name, PPPInterface& interface, driver_parameter *settings) - : fInterface(interface), fSettings(settings) + : fInterface(interface), fSettings(settings), fEnabled(true) { if(name) { strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); @@ -44,12 +44,12 @@ status_t PPPOptionHandler::Control(uint32 op, void *data, size_t length) { switch(op) { - case PPPC_GET_OPTION_HANDLER_INFO: { - if(length < sizeof(ppp_option_handler_info) || !data) + case PPPC_GET_SIMPLE_HANDLER_INFO: { + if(length < sizeof(ppp_simple_handler_info_t) || !data) return B_ERROR; - ppp_option_handler_info *info = (ppp_option_handler_info*) data; - memset(info, 0, sizeof(ppp_option_handler_info)); + ppp_simple_handler_info *info = (ppp_simple_handler_info*) data; + memset(info, 0, sizeof(ppp_simple_handler_info_t)); strcpy(info->name, Name()); info->settings = Settings(); info->isEnabled = IsEnabled(); diff --git a/src/tests/kits/net/ppp/src/KPPPReportManager.cpp b/src/tests/kits/net/ppp/src/KPPPReportManager.cpp index 7814ea224d..fc884dd035 100644 --- a/src/tests/kits/net/ppp/src/KPPPReportManager.cpp +++ b/src/tests/kits/net/ppp/src/KPPPReportManager.cpp @@ -28,7 +28,7 @@ PPPReportManager::~PPPReportManager() void PPPReportManager::EnableReports(PPP_REPORT_TYPE type, thread_id thread, - int32 flags = PPP_NO_REPORT_FLAGS) + int32 flags = PPP_NO_FLAGS) { LockerHelper locker(fLock); @@ -54,7 +54,7 @@ PPPReportManager::DisableReports(PPP_REPORT_TYPE type, thread_id thread) if(request->thread != thread) continue; - if(request->type == type) + if(request->type == type || request->type == PPP_ALL_REPORTS) fReportRequests.RemoveItem(request); } } diff --git a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp index 0bd44d1459..e5ed171937 100644 --- a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp +++ b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -701,16 +702,19 @@ PPPStateMachine::RCRGoodEvent(struct mbuf *packet) case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RCR_GOOD_EVENT); + m_freem(packet); break; case PPP_CLOSED_STATE: locker.UnlockNow(); - SendTerminateAck(packet); + SendTerminateAck(); + m_freem(packet); break; case PPP_STOPPED_STATE: // irc,scr,sca/8 // XXX: should we do nothing and wait for DownEvent()? + m_freem(packet); break; case PPP_REQ_SENT_STATE: @@ -740,7 +744,7 @@ PPPStateMachine::RCRGoodEvent(struct mbuf *packet) break; default: - ; + m_freem(packet); } } @@ -759,7 +763,7 @@ PPPStateMachine::RCRBadEvent(struct mbuf *nak, struct mbuf *reject) case PPP_CLOSED_STATE: locker.UnlockNow(); - SendTerminateAck(NULL); + SendTerminateAck(); break; case PPP_STOPPED_STATE: @@ -787,11 +791,17 @@ PPPStateMachine::RCRBadEvent(struct mbuf *nak, struct mbuf *reject) SendConfigureNak(nak); else if(reject && ntohs(mtod(reject, ppp_lcp_packet*)->length) > 3) SendConfigureNak(reject); - break; + return; + // prevents the nak/reject from being m_freem()'d default: ; } + + if(nak) + m_freem(nak); + if(reject) + m_freem(reject); } @@ -806,12 +816,13 @@ PPPStateMachine::RCAEvent(struct mbuf *packet) // TODO: // log this event + m_freem(packet); return; } - PPPOptionHandler *handler; + // let the option handlers parse this ack PPPConfigurePacket ack(packet); - + PPPOptionHandler *handler; for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) { handler = LCP().OptionHandlerAt(index); handler->ParseAck(&ack); @@ -826,7 +837,7 @@ PPPStateMachine::RCAEvent(struct mbuf *packet) case PPP_CLOSED_STATE: case PPP_STOPPED_STATE: locker.UnlockNow(); - SendTerminateAck(NULL); + SendTerminateAck(); break; case PPP_REQ_SENT_STATE: @@ -859,6 +870,8 @@ PPPStateMachine::RCAEvent(struct mbuf *packet) default: ; } + + m_freem(packet); } @@ -873,12 +886,13 @@ PPPStateMachine::RCNEvent(struct mbuf *packet) // TODO: // log this event + m_freem(packet); return; } - PPPOptionHandler *handler; + // let the option handlers parse this nak/reject PPPConfigurePacket nak_reject(packet); - + PPPOptionHandler *handler; for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) { handler = LCP().OptionHandlerAt(index); @@ -897,7 +911,7 @@ PPPStateMachine::RCNEvent(struct mbuf *packet) case PPP_CLOSED_STATE: case PPP_STOPPED_STATE: locker.UnlockNow(); - SendTerminateAck(packet); + SendTerminateAck(); break; case PPP_REQ_SENT_STATE: @@ -923,6 +937,8 @@ PPPStateMachine::RCNEvent(struct mbuf *packet) default: ; } + + m_freem(packet); } @@ -943,6 +959,7 @@ PPPStateMachine::RTREvent(struct mbuf *packet) case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RTR_EVENT); + m_freem(packet); break; case PPP_ACK_RCVD_STATE: @@ -984,6 +1001,7 @@ PPPStateMachine::RTAEvent(struct mbuf *packet) // TODO: // log this event + m_freem(packet); return; } @@ -1019,12 +1037,15 @@ PPPStateMachine::RTAEvent(struct mbuf *packet) default: ; } + + m_freem(packet); } // receive unknown code void -PPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocol, uint8 type = PPP_PROTOCOL_REJECT) +PPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocol, + uint8 code = PPP_PROTOCOL_REJECT) { LockerHelper locker(fLock); @@ -1032,11 +1053,12 @@ PPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocol, uint8 type = PPP case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RUC_EVENT); + m_freem(packet); break; default: locker.UnlockNow(); - SendCodeReject(packet, protocol, type); + SendCodeReject(packet, protocol, code); } } @@ -1102,6 +1124,8 @@ PPPStateMachine::RXJBadEvent(struct mbuf *packet) SendTerminateRequest(); break; } + + m_freem(packet); } @@ -1120,11 +1144,13 @@ PPPStateMachine::RXREvent(struct mbuf *packet) case PPP_OPENED_STATE: if(echo->code == PPP_ECHO_REQUEST) SendEchoReply(packet); - break; + return; default: ; } + + m_freem(packet); } @@ -1199,6 +1225,7 @@ PPPStateMachine::RCREvent(struct mbuf *packet) else if(error == B_ERROR) { // the request contains a value that has been sent more than // once or the value is corrupted + m_freem(packet); CloseEvent(); return; } else if(error == B_OK) @@ -1226,14 +1253,34 @@ PPPStateMachine::RCREvent(struct mbuf *packet) void PPPStateMachine::RXJEvent(struct mbuf *packet) { - ppp_lcp_packet *reject mtod(packet, ppp_lcp_packet*); + ppp_lcp_packet *reject = mtod(packet, ppp_lcp_packet*); if(reject->code == PPP_CODE_REJECT) { - // we only have basic codes, so there must be something wrong - if(Interface()->IsMultilink() && !Interface()->Parent()) - CloseEvent(); - else - RXJBadEvent(packet); + uint8 rejectedCode = reject->data[0]; + + // test if the rejected code belongs to the minimum LCP requirements + if(rejectedCode >= PPP_MIN_LCP_CODE && rejectedCode <= PPP_MAX_LCP_CODE) { + if(Interface()->IsMultilink() && !Interface()->Parent()) { + // Main interfaces do not have states between STARTING and OPENED. + // An RXJBadEvent() would enter one of those states which is bad. + m_freem(packet); + CloseEvent(); + } else + RXJBadEvent(packet); + + return; + } + + // find the LCP extension and disable it + PPPLCPExtension *extension; + for(int32 index = 0; index < LCP().CountLCPExtensions(); index++) { + extension = LCP().LCPExtensionAt(index); + + if(extension->Code() == rejectedCode) + extension->SetEnabled(false); + } + + m_freem(packet); } else if(reject->code == PPP_PROTOCOL_REJECT) { // disable all handlers for rejected protocol type uint16 rejected = *((uint16*) reject->data); @@ -1245,6 +1292,7 @@ PPPStateMachine::RXJEvent(struct mbuf *packet) return; } + // disable protocols and encapsulators with the rejected protocl number int32 index; PPPProtocol *protocol_handler; PPPEncapsulator *encapsulator_handler = Interface()->FirstEncapsulator(); @@ -1264,10 +1312,13 @@ PPPStateMachine::RXJEvent(struct mbuf *packet) } RXJGoodEvent(packet); + // this event handler does not m_freem(packet)!!! // notify parent, too if(Interface()->Parent()) Interface()->Parent()->StateMachine().RXJEvent(packet); + else + m_freem(packet); } } @@ -1374,9 +1425,13 @@ PPPStateMachine::SendConfigureRequest() void PPPStateMachine::SendConfigureAck(struct mbuf *packet) { + if(!packet) + return; + mtod(packet, ppp_lcp_packet*)->code = PPP_CONFIGURE_ACK; PPPConfigurePacket ack(packet); + // notify all option handlers that we are sending an ack for each value for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) LCP().OptionHandlerAt(index)->SendingAck(&ack); @@ -1387,6 +1442,9 @@ PPPStateMachine::SendConfigureAck(struct mbuf *packet) void PPPStateMachine::SendConfigureNak(struct mbuf *packet) { + if(!packet) + return; + ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*); if(nak->code == PPP_CONFIGURE_NAK) { if(fNakCounter == 0) { @@ -1424,7 +1482,7 @@ PPPStateMachine::SendTerminateRequest() void -PPPStateMachine::SendTerminateAck(struct mbuf *request) +PPPStateMachine::SendTerminateAck(struct mbuf *request = NULL) { struct mbuf *reply = request; @@ -1440,26 +1498,32 @@ PPPStateMachine::SendTerminateAck(struct mbuf *request) ack = mtod(reply, ppp_lcp_packet*); ack->id = NextID(); - ack->length = 4; } ack = mtod(reply, ppp_lcp_packet*); ack->code = PPP_TERMINATE_ACK; + ack->length = 4; LCP().Send(reply); } void -PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type) +PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 code) { + if(!packet) + return; + int32 length; // additional space needed for this reject - if(type == PPP_PROTOCOL_REJECT) + if(code == PPP_PROTOCOL_REJECT) length = 6; else length = 4; + M_PREPEND(packet, length); + // add some space for the header + int32 adjust = 0; // adjust packet size by this value if packet is too big if(packet->m_flags & M_PKTHDR) { @@ -1472,7 +1536,7 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type m_adj(packet, adjust); ppp_lcp_packet *reject = mtod(packet, ppp_lcp_packet*); - reject->code = type; + reject->code = code; reject->id = NextID(); if(packet->m_flags & M_PKTHDR) reject->length = htons(packet->m_pkthdr.len); @@ -1480,7 +1544,7 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type reject->length = htons(packet->m_len); protocol = htons(protocol); - if(type == PPP_PROTOCOL_REJECT) + if(code == PPP_PROTOCOL_REJECT) memcpy(&reject->data, &protocol, sizeof(protocol)); LCP().Send(packet); @@ -1490,6 +1554,9 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type void PPPStateMachine::SendEchoReply(struct mbuf *request) { + if(!request) + return; + ppp_lcp_packet *reply = mtod(request, ppp_lcp_packet*); reply->code = PPP_ECHO_REPLY; // the request becomes a reply @@ -1589,4 +1656,7 @@ PPPStateMachine::ResetOptionHandlers() { for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) LCP().OptionHandlerAt(index)->Reset(); + + for(int32 index = 0; index < LCP().CountLCPExtensions(); index++) + LCP().LCPExtensionAt(index)->Reset(); }