From 7ff713dadd491a669a12512b0101380e359a76c0 Mon Sep 17 00:00:00 2001 From: Waldemar Kornewald Date: Sat, 13 Sep 2003 17:57:12 +0000 Subject: [PATCH] Replaced some pointers with references. Added support for Protocol-Field-Compression including the needed handler. Added initial support for ppp_manager's ioctl() function (currently, PPPInterface does not handle any ioctls). These calls are routed to all handlers, too (if PPPInterface did not handle the ioctl). Changed naming of local states and report codes (authentication, etc.). These now have "Local"/"LOCAL" in their name. Some minor changes. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4672 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/tests/kits/net/ppp/headers/KPPP.h | 7 + src/tests/kits/net/ppp/headers/KPPPDevice.h | 3 +- .../kits/net/ppp/headers/KPPPEncapsulator.h | 3 +- .../kits/net/ppp/headers/KPPPInterface.h | 24 +- .../kits/net/ppp/headers/KPPPLCPExtension.h | 7 +- .../kits/net/ppp/headers/KPPPOptionHandler.h | 28 ++- src/tests/kits/net/ppp/headers/KPPPProtocol.h | 4 +- .../kits/net/ppp/headers/KPPPStateMachine.h | 18 +- src/tests/kits/net/ppp/headers/PPPControl.h | 12 +- src/tests/kits/net/ppp/headers/PPPDefs.h | 22 +- .../kits/net/ppp/headers/PPPReportDefs.h | 7 +- src/tests/kits/net/ppp/src/Jamfile | 3 + src/tests/kits/net/ppp/src/KPPPDevice.cpp | 10 +- .../kits/net/ppp/src/KPPPEncapsulator.cpp | 20 +- src/tests/kits/net/ppp/src/KPPPInterface.cpp | 238 +++++++++++++++--- src/tests/kits/net/ppp/src/KPPPLCP.cpp | 3 +- .../kits/net/ppp/src/KPPPLCPExtension.cpp | 10 +- .../kits/net/ppp/src/KPPPOptionHandler.cpp | 10 +- src/tests/kits/net/ppp/src/KPPPProtocol.cpp | 19 +- .../kits/net/ppp/src/KPPPReportManager.cpp | 6 +- .../kits/net/ppp/src/KPPPStateMachine.cpp | 189 +++++++++----- .../kits/net/ppp/src/_KPPPPFCHandler.cpp | 120 +++++++++ src/tests/kits/net/ppp/src/_KPPPPFCHandler.h | 35 +++ 23 files changed, 630 insertions(+), 168 deletions(-) create mode 100644 src/tests/kits/net/ppp/src/_KPPPPFCHandler.cpp create mode 100644 src/tests/kits/net/ppp/src/_KPPPPFCHandler.h diff --git a/src/tests/kits/net/ppp/headers/KPPP.h b/src/tests/kits/net/ppp/headers/KPPP.h index 922f832530..2b08ec19fa 100644 --- a/src/tests/kits/net/ppp/headers/KPPP.h +++ b/src/tests/kits/net/ppp/headers/KPPP.h @@ -1,3 +1,10 @@ +//---------------------------------------------------------------------- +// 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__H #define _K_PPP__H diff --git a/src/tests/kits/net/ppp/headers/KPPPDevice.h b/src/tests/kits/net/ppp/headers/KPPPDevice.h index cc3fdc3a70..3bac05dd68 100644 --- a/src/tests/kits/net/ppp/headers/KPPPDevice.h +++ b/src/tests/kits/net/ppp/headers/KPPPDevice.h @@ -78,12 +78,13 @@ class PPPDevice { protected: uint32 fMTU; bool fIsUp; + + status_t fInitStatus; private: char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; PPPInterface& fInterface; driver_parameter *fSettings; - status_t fInitStatus; }; diff --git a/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h b/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h index adc12d30a0..34839a6ba9 100644 --- a/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h +++ b/src/tests/kits/net/ppp/headers/KPPPEncapsulator.h @@ -99,6 +99,8 @@ class PPPEncapsulator { protected: uint32 fOverhead; + + status_t fInitStatus; private: char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; @@ -115,7 +117,6 @@ class PPPEncapsulator { bool fEnabled; bool fUpRequested; ppp_phase fConnectionStatus; - status_t fInitStatus; }; diff --git a/src/tests/kits/net/ppp/headers/KPPPInterface.h b/src/tests/kits/net/ppp/headers/KPPPInterface.h index cbff4bf861..06a985bb06 100644 --- a/src/tests/kits/net/ppp/headers/KPPPInterface.h +++ b/src/tests/kits/net/ppp/headers/KPPPInterface.h @@ -141,6 +141,21 @@ class PPPInterface { ppp_phase Phase() const { return fStateMachine.Phase(); } + // Protocol-Field-Compression + bool SetPFCOptions(uint8 pfcOptions); + uint8 PFCOptions() const + { return fPFCOptions; } + ppp_pfc_state LocalPFCState() const + { return fLocalPFCState; } + // the local PFC state says if we accepted a request from the peer + // i.e.: we may use PFC in outgoing packets + ppp_pfc_state PeerPFCState() const + { return fPeerPFCState; } + // the peer PFC state says if the peer accepted a request us + // i.e.: the peer might send PFC-compressed packets to us + bool UseLocalPFC() const + { return LocalPFCState() & PPP_PFC_ACCEPTED; } + bool Up(); // in server mode Up() listens for an incoming connection bool Down(); @@ -175,6 +190,11 @@ class PPPInterface { // saves the returned ifnet structure bool UnregisterInterface(); + status_t StackControl(uint32 op, void *data); + // stack routes ioctls to interface + status_t ControlEachHandler(uint32 op, void *data, size_t length); + // this calls Control() with the given parameters for each handler + void CalculateInterfaceMTU(); void CalculateBaudRate(); @@ -213,9 +233,9 @@ class PPPInterface { bool fAutoRedial, fDialOnDemand; - vint32 fAccesing; - ppp_mode fMode; + ppp_pfc_state fLocalPFCState, fPeerPFCState; + uint8 fPFCOptions; PPPDevice *fDevice; PPPEncapsulator *fFirstEncapsulator; diff --git a/src/tests/kits/net/ppp/headers/KPPPLCPExtension.h b/src/tests/kits/net/ppp/headers/KPPPLCPExtension.h index 67d53b230e..39da7dd415 100644 --- a/src/tests/kits/net/ppp/headers/KPPPLCPExtension.h +++ b/src/tests/kits/net/ppp/headers/KPPPLCPExtension.h @@ -41,12 +41,14 @@ class PPPLCPExtension { 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 Reset(); virtual void Pulse(); + protected: + status_t fInitStatus; + private: char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; PPPInterface& fInterface; @@ -54,7 +56,6 @@ class PPPLCPExtension { uint8 fCode; bool fEnabled; - status_t fInitStatus; }; diff --git a/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h b/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h index 848ef5c700..0674f686e7 100644 --- a/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h +++ b/src/tests/kits/net/ppp/headers/KPPPOptionHandler.h @@ -43,25 +43,28 @@ class PPPOptionHandler { virtual status_t Control(uint32 op, void *data, size_t length); - virtual void Reset() = 0; - // e.g.: remove list of rejected values - // we want to send a configure request or we received a reply - virtual status_t AddToRequest(PPPConfigurePacket *request) = 0; - virtual void ParseNak(const PPPConfigurePacket *nak) = 0; + virtual status_t AddToRequest(PPPConfigurePacket& request) = 0; + virtual status_t ParseNak(const PPPConfigurePacket& nak) = 0; // create next request based on these and previous values - virtual void ParseReject(const PPPConfigurePacket *reject) = 0; + virtual status_t ParseReject(const PPPConfigurePacket& reject) = 0; // create next request based on these and previous values - virtual void ParseAck(const PPPConfigurePacket *ack) = 0; + virtual status_t ParseAck(const PPPConfigurePacket& ack) = 0; // this is called for all handlers // peer sent configure request - virtual status_t ParseRequest(const PPPConfigurePacket *request, - int32 item, PPPConfigurePacket *nak, PPPConfigurePacket *reject) = 0; - // item may be behind the last item which means we can add - // additional values - virtual void SendingAck(const PPPConfigurePacket *ack) = 0; + virtual status_t ParseRequest(const PPPConfigurePacket& request, + int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject) = 0; + // index may be behind the last item which means additional values can be + // appended + virtual status_t SendingAck(const PPPConfigurePacket& ack) = 0; // notification that we ack these values + + virtual void Reset() = 0; + // e.g.: remove list of rejected values + + protected: + status_t fInitStatus; private: char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; @@ -70,7 +73,6 @@ class PPPOptionHandler { driver_parameter *fSettings; bool fEnabled; - status_t fInitStatus; }; diff --git a/src/tests/kits/net/ppp/headers/KPPPProtocol.h b/src/tests/kits/net/ppp/headers/KPPPProtocol.h index a9cebb56cd..03b0587046 100644 --- a/src/tests/kits/net/ppp/headers/KPPPProtocol.h +++ b/src/tests/kits/net/ppp/headers/KPPPProtocol.h @@ -90,6 +90,9 @@ class PPPProtocol { void DownEvent(); // report up/down events + protected: + status_t fInitStatus; + private: char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; ppp_phase fPhase; @@ -103,7 +106,6 @@ class PPPProtocol { bool fEnabled; bool fUpRequested; ppp_phase fConnectionStatus; - status_t fInitStatus; }; diff --git a/src/tests/kits/net/ppp/headers/KPPPStateMachine.h b/src/tests/kits/net/ppp/headers/KPPPStateMachine.h index 1d5aec6538..1939eb669c 100644 --- a/src/tests/kits/net/ppp/headers/KPPPStateMachine.h +++ b/src/tests/kits/net/ppp/headers/KPPPStateMachine.h @@ -58,13 +58,13 @@ class PPPStateMachine { bool SendDiscardRequest(); // public events - void AuthenticationRequested(); - void AuthenticationAccepted(const char *name); - void AuthenticationDenied(const char *name); - const char *AuthenticationName() const - { return fAuthenticationName; } - ppp_authentication_status AuthenticationStatus() const - { return fAuthenticationStatus; } + void LocalAuthenticationRequested(); + void LocalAuthenticationAccepted(const char *name); + void LocalAuthenticationDenied(const char *name); + const char *LocalAuthenticationName() const + { return fLocalAuthenticationName; } + ppp_authentication_status LocalAuthenticationStatus() const + { return fLocalAuthenticationStatus; } void PeerAuthenticationRequested(); void PeerAuthenticationAccepted(const char *name); @@ -159,9 +159,9 @@ class PPPStateMachine { vint32 fID; uint32 fMagicNumber; - ppp_authentication_status fAuthenticationStatus, + ppp_authentication_status fLocalAuthenticationStatus, fPeerAuthenticationStatus; - char *fAuthenticationName, *fPeerAuthenticationName; + char *fLocalAuthenticationName, *fPeerAuthenticationName; BLocker fLock; diff --git a/src/tests/kits/net/ppp/headers/PPPControl.h b/src/tests/kits/net/ppp/headers/PPPControl.h index 05fee60457..a6bcd1e3cd 100644 --- a/src/tests/kits/net/ppp/headers/PPPControl.h +++ b/src/tests/kits/net/ppp/headers/PPPControl.h @@ -59,6 +59,10 @@ enum ppp_control_ops { PPPC_SET_ENABLED, PPPC_GET_SIMPLE_HANDLER_INFO, // PPPOptionHandler and PPPLCPExtension + PPPC_STACK_IOCTL, + // Ioctls from the stack are passed to all handlers and the interface + // using a ppp_control_info (only op and data are defined!). + // You should return B_BAD_VALUE if you did not handle this ioctl. // ----------------------------------------------------- PPP_CONTROL_OPS_END = B_DEVICE_OP_CODES_END + 0xFFFF @@ -89,13 +93,17 @@ typedef struct ppp_interface_info { ppp_mode mode; ppp_state state; ppp_phase phase; - ppp_authentication_status authenticationStatus, peerAuthenticationStatus; + ppp_authentication_status localAuthenticationStatus, peerAuthenticationStatus; + ppp_pfc_state localPFCState, peerPFCState; + uint8 pfcOptions; uint32 protocolsCount, encapsulatorsCount, optionHandlersCount, LCPExtensionsCount, childrenCount; uint32 MRU, interfaceMTU; - bigtime_t idleSince, disconnectAfterIdleSince; + uint32 dialRetry, dialRetriesLimit; + uint32 dialRetryDelay, redialDelay; + uint32 idleSince, disconnectAfterIdleSince; bool doesDialOnDemand, doesAutoRedial, hasDevice, isMultilink, hasParent; } ppp_interface_info; diff --git a/src/tests/kits/net/ppp/headers/PPPDefs.h b/src/tests/kits/net/ppp/headers/PPPDefs.h index e79f0c20dd..cf629f6b8a 100644 --- a/src/tests/kits/net/ppp/headers/PPPDefs.h +++ b/src/tests/kits/net/ppp/headers/PPPDefs.h @@ -62,6 +62,25 @@ enum { // could not send a packet because device is not connected }; +// PFC options +enum { + PPP_REQUEST_PFC = 0x01, + // try to request PFC (does not fail if not successful) + PPP_ALLOW_PFC = 0x02, + // allow PFC if other side requests it + PPP_FORCE_PFC_REQUEST = 0x04, + // if PFC request fails the connection attempt will terminate + PPP_FREEZE_PFC_OPTIONS = 0x80 + // the options cannot be changed if this flag is set (mainly used by PPPDevice) +}; + +enum ppp_pfc_state { + PPP_PFC_DISABLED, + PPP_PFC_ACCEPTED, + PPP_PFC_REJECTED + // not used for peer state +}; + // protocol and encapsulator flags enum { PPP_NO_FLAGS = 0x00, @@ -100,7 +119,8 @@ enum ppp_phase { // this defines the order in which the packets get encapsulated enum ppp_encapsulation_level { - PPP_MULTILINK_LEVEL = 0, + PPP_DEVICE_LEVEL = 0, + PPP_MULTILINK_LEVEL = 2, PPP_ENCRYPTION_LEVEL = 5, PPP_COMPRESSION_LEVEL = 10 }; diff --git a/src/tests/kits/net/ppp/headers/PPPReportDefs.h b/src/tests/kits/net/ppp/headers/PPPReportDefs.h index 1e6e64d413..664b561947 100644 --- a/src/tests/kits/net/ppp/headers/PPPReportDefs.h +++ b/src/tests/kits/net/ppp/headers/PPPReportDefs.h @@ -41,10 +41,11 @@ enum ppp_connection_report_codes { PPP_REPORT_DOWN_SUCCESSFUL = 2, PPP_REPORT_UP_ABORTED = 3, PPP_REPORT_DEVICE_UP_FAILED = 4, - PPP_REPORT_AUTHENTICATION_SUCCESSFUL = 5, + PPP_REPORT_LOCAL_AUTHENTICATION_SUCCESSFUL = 5, PPP_REPORT_PEER_AUTHENTICATION_SUCCESSFUL = 6, - PPP_REPORT_AUTHENTICATION_FAILED = 7, - PPP_REPORT_CONNECTION_LOST = 8 + PPP_REPORT_LOCAL_AUTHENTICATION_FAILED = 7, + PPP_REPORT_PEER_AUTHENTICATION_FAILED = 8, + PPP_REPORT_CONNECTION_LOST = 9 }; diff --git a/src/tests/kits/net/ppp/src/Jamfile b/src/tests/kits/net/ppp/src/Jamfile index 96452a80ec..353cf2e936 100644 --- a/src/tests/kits/net/ppp/src/Jamfile +++ b/src/tests/kits/net/ppp/src/Jamfile @@ -23,5 +23,8 @@ R5KernelStaticLibrary kernelppp : Locker.cpp settings_tools.cpp cpp.cpp + + # integrated modules + _KPPPPFCHandler.cpp ; diff --git a/src/tests/kits/net/ppp/src/KPPPDevice.cpp b/src/tests/kits/net/ppp/src/KPPPDevice.cpp index 86ef5e3bd6..5d845f3662 100644 --- a/src/tests/kits/net/ppp/src/KPPPDevice.cpp +++ b/src/tests/kits/net/ppp/src/KPPPDevice.cpp @@ -15,7 +15,10 @@ PPPDevice::PPPDevice(const char *name, PPPInterface& interface, driver_parameter *settings) - : fMTU(1500), fIsUp(false), fInterface(interface), fSettings(settings) + : fMTU(1500), + fIsUp(false), + fInterface(interface), + fSettings(settings) { if(name) { strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); @@ -36,9 +39,6 @@ PPPDevice::~PPPDevice() status_t PPPDevice::InitCheck() const { - if(!Settings()) - return B_ERROR; - return fInitStatus; } @@ -63,7 +63,7 @@ PPPDevice::Control(uint32 op, void *data, size_t length) } break; default: - return PPP_UNHANDLED; + return B_BAD_VALUE; } return B_OK; diff --git a/src/tests/kits/net/ppp/src/KPPPEncapsulator.cpp b/src/tests/kits/net/ppp/src/KPPPEncapsulator.cpp index 84091ce914..cc494492c9 100644 --- a/src/tests/kits/net/ppp/src/KPPPEncapsulator.cpp +++ b/src/tests/kits/net/ppp/src/KPPPEncapsulator.cpp @@ -16,10 +16,17 @@ PPPEncapsulator::PPPEncapsulator(const char *name, ppp_phase phase, int32 addressFamily, uint32 overhead, PPPInterface& interface, driver_parameter *settings, int32 flags = PPP_NO_FLAGS) - : fOverhead(overhead), fPhase(phase), fLevel(level), fProtocol(protocol), - fAddressFamily(addressFamily), fInterface(interface), - fSettings(settings), fFlags(flags), fEnabled(true), - fUpRequested(true), fConnectionStatus(PPP_DOWN_PHASE) + : fOverhead(overhead), + fPhase(phase), + fLevel(level), + fProtocol(protocol), + fAddressFamily(addressFamily), + fInterface(interface), + fSettings(settings), + fFlags(flags), + fEnabled(true), + fUpRequested(true), + fConnectionStatus(PPP_DOWN_PHASE) { if(name) { strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); @@ -40,9 +47,6 @@ PPPEncapsulator::~PPPEncapsulator() status_t PPPEncapsulator::InitCheck() const { - if(!Settings()) - return B_ERROR; - return fInitStatus; } @@ -91,7 +95,7 @@ PPPEncapsulator::Control(uint32 op, void *data, size_t length) break; default: - return PPP_UNHANDLED; + return B_BAD_VALUE; } return B_OK; diff --git a/src/tests/kits/net/ppp/src/KPPPInterface.cpp b/src/tests/kits/net/ppp/src/KPPPInterface.cpp index 339c4c5ded..2b2439d833 100644 --- a/src/tests/kits/net/ppp/src/KPPPInterface.cpp +++ b/src/tests/kits/net/ppp/src/KPPPInterface.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,9 @@ // tools only for us :) #include "settings_tools.h" +// internal modules +#include "_KPPPPFCHandler.h" + // TODO: // - implement timers with support for settings next time instead of receiving timer @@ -52,13 +56,36 @@ status_t interface_deleter_thread(void *data); PPPInterface::PPPInterface(uint32 ID, driver_settings *settings, PPPInterface *parent = NULL) - : fID(ID), fSettings(dup_driver_settings(settings)), - fStateMachine(*this), fLCP(*this), fReportManager(StateMachine().Locker()), - fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0), - fDialRetriesLimit(0), fIdleSince(0), fMRU(1500), fInterfaceMTU(1498), - fHeaderLength(2), fAutoRedial(false), fDialOnDemand(false), fDevice(NULL), - fFirstEncapsulator(NULL), fLock(StateMachine().Locker()), fDeleteCounter(0) + : fID(ID), + fSettings(dup_driver_settings(settings)), + fStateMachine(*this), + fLCP(*this), + fReportManager(StateMachine().Locker()), + fIfnet(NULL), + fUpThread(-1), + fRedialThread(-1), + fDialRetry(0), + fDialRetriesLimit(0), + fIdleSince(0), + fMRU(1500), + fInterfaceMTU(1498), + fHeaderLength(2), + fAutoRedial(false), + fDialOnDemand(false), + fLocalPFCState(PPP_PFC_DISABLED), + fPeerPFCState(PPP_PFC_DISABLED), + fPFCOptions(0), + fDevice(NULL), + fFirstEncapsulator(NULL), + fLock(StateMachine().Locker()), + fDeleteCounter(0) { + // add internal modules + _PPPPFCHandler *pfcHandler = + new _PPPPFCHandler(fLocalPFCState, fPeerPFCState, *this); + if(pfcHandler->InitCheck() != B_OK) + delete pfcHandler; + // set up dial delays fDialRetryDelay = 3000; // 3s delay between each new attempt to redial @@ -253,9 +280,13 @@ PPPInterface::Control(uint32 op, void *data, size_t length) info->mode = Mode(); info->state = State(); info->phase = Phase(); - info->authenticationStatus = StateMachine().AuthenticationStatus(); + info->localAuthenticationStatus = + StateMachine().LocalAuthenticationStatus(); info->peerAuthenticationStatus = StateMachine().PeerAuthenticationStatus(); + info->localPFCState = LocalPFCState(); + info->peerPFCState = PeerPFCState(); + info->pfcOptions = PFCOptions(); info->protocolsCount = CountProtocols(); info->encapsulatorsCount = CountEncapsulators(); info->optionHandlersCount = LCP().CountOptionHandlers(); @@ -263,6 +294,10 @@ PPPInterface::Control(uint32 op, void *data, size_t length) info->childrenCount = CountChildren(); info->MRU = MRU(); info->interfaceMTU = InterfaceMTU(); + info->dialRetry = fDialRetry; + info->dialRetriesLimit = fDialRetriesLimit; + info->dialRetryDelay = DialRetryDelay(); + info->redialDelay = RedialDelay(); info->idleSince = IdleSince(); info->disconnectAfterIdleSince = DisconnectAfterIdleSince(); info->doesDialOnDemand = DoesDialOnDemand(); @@ -361,7 +396,16 @@ PPPInterface::Control(uint32 op, void *data, size_t length) } break; case PPPC_CONTROL_LCP_EXTENSION: { - return PPP_UNHANDLED; + if(length < sizeof(ppp_control_info) || !data) + return B_ERROR; + + ppp_control_info *control = (ppp_control_info*) data; + PPPLCPExtension *extension_handler = LCP().LCPExtensionAt(control->index); + if(!extension_handler) + return B_BAD_INDEX; + + return extension_handler->Control(control->op, control->data, + control->length); } break; case PPPC_CONTROL_CHILD: { @@ -376,8 +420,19 @@ PPPInterface::Control(uint32 op, void *data, size_t length) return child->Control(control->op, control->data, control->length); } break; + case PPPC_STACK_IOCTL: { + if(length < sizeof(ppp_control_info) || !data) + return B_ERROR; + + ppp_control_info *control = (ppp_control_info*) data; + if(StackControl(control->op, control->data) == B_BAD_VALUE) + return ControlEachHandler(op, data, length); + + return B_OK; + } break; + default: - return PPP_UNHANDLED; + return B_BAD_VALUE; } return B_OK; @@ -718,6 +773,17 @@ PPPInterface::SetDialOnDemand(bool dialondemand = true) } +bool +PPPInterface::SetPFCOptions(uint8 pfcOptions) +{ + if(PFCOptions() & PPP_FREEZE_PFC_OPTIONS) + return false; + + fPFCOptions = pfcOptions; + return true; +} + + bool PPPInterface::Up() { @@ -742,9 +808,13 @@ PPPInterface::Up() fLock.Unlock(); // fUpThread tells the state machine to go up - if(me == fUpThread) + if(me == fUpThread || me == fRedialThread) StateMachine().OpenEvent(); + if(me == fRedialThread && me != fUpThread) + return true; + // the redial thread is doing a DialRetry in this case + while(true) { if(IsUp()) { // lock needs timeout because destructor could have locked the interface @@ -763,6 +833,9 @@ PPPInterface::Up() return true; } + // A wrong code usually happens when the redial thread gets notified + // of a Down() request. In that case a report will follow soon, so + // this can be ignored. if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE) continue; @@ -798,6 +871,8 @@ PPPInterface::Up() if(me == fUpThread) { fDialRetry = 0; fUpThread = -1; + send_data_with_timeout(fRedialThread, 0, NULL, 0, 200); + // notify redial thread that we do not need it anymore } PPP_REPLY(sender, B_OK); @@ -805,7 +880,8 @@ PPPInterface::Up() return true; } else if(report.code == PPP_REPORT_DOWN_SUCCESSFUL || report.code == PPP_REPORT_UP_ABORTED - || report.code == PPP_REPORT_AUTHENTICATION_FAILED) { + || report.code == PPP_REPORT_LOCAL_AUTHENTICATION_FAILED + || report.code == PPP_REPORT_PEER_AUTHENTICATION_FAILED) { if(me == fUpThread) { fDialRetry = 0; fUpThread = -1; @@ -857,7 +933,7 @@ PPPInterface::Up() } else { ++fDialRetry; PPP_REPLY(sender, B_OK); - StateMachine().OpenEvent(); + Redial(DialRetryDelay()); continue; } } else if(report.code == PPP_REPORT_CONNECTION_LOST) { @@ -866,7 +942,7 @@ PPPInterface::Up() if(DoesAutoRedial() && fDialRetry < fDialRetriesLimit) { ++fDialRetry; PPP_REPLY(sender, B_OK); - StateMachine().OpenEvent(); + Redial(DialRetryDelay()); continue; } else { fDialRetry = 0; @@ -897,6 +973,9 @@ PPPInterface::Down() if(InitCheck() != B_OK) return false; + send_data_with_timeout(fRedialThread, 0, NULL, 0, 200); + // the redial thread should be notified that the user wants to disconnect + // this locked section guarantees that there are no state changes before we // enable the connection reports LockerHelper locker(fLock); @@ -1218,16 +1297,26 @@ PPPInterface::SendToDevice(struct mbuf *packet, uint16 protocol) return B_ERROR; } - // encode in ppp frame - M_PREPEND(packet, 2); - - if(packet == NULL) - return B_ERROR; - - // set protocol (the only header field) - protocol = htons(protocol); - uint16 *header = mtod(packet, uint16*); - *header = protocol; + // encode in ppp frame and consider using PFC + if(UseLocalPFC() && protocol & 0xFF00 == 0) { + M_PREPEND(packet, 1); + + if(packet == NULL) + return B_ERROR; + + uint8 *header = mtod(packet, uint8*); + *header = protocol & 0xFF; + } else { + M_PREPEND(packet, 2); + + if(packet == NULL) + return B_ERROR; + + // set protocol (the only header field) + protocol = htons(protocol); + uint16 *header = mtod(packet, uint16*); + *header = protocol; + } fIdleSince = real_time_clock(); @@ -1260,13 +1349,16 @@ PPPInterface::ReceiveFromDevice(struct mbuf *packet) return B_ERROR; } - // decode ppp frame - uint16 *protocol = mtod(packet, uint16*); - *protocol = ntohs(*protocol); + // decode ppp frame and recognize PFC + uint16 protocol = *mtod(packet, uint8*); + if(protocol == 0) + m_adj(packet, 1); + else { + protocol = ntohs(*mtod(packet, uint16*)); + m_adj(packet, 2); + } - m_adj(packet, 2); - - return Receive(packet, *protocol); + return Receive(packet, protocol); } @@ -1351,6 +1443,89 @@ PPPInterface::UnregisterInterface() } +// stack routes ioctls to interface +status_t +PPPInterface::StackControl(uint32 op, void *data) +{ + // TODO: + // implement when writing ppp_manager module + + switch(op) { + default: + return B_BAD_VALUE; + } + + return B_OK; +} + + +// This calls Control() with the given parameters for each handler. +// Return values: +// B_OK: all handlers returned B_OK +// B_BAD_VALUE: no handler was found +// any other value: the error value that was returned by the last handler that failed +status_t +PPPInterface::ControlEachHandler(uint32 op, void *data, size_t length) +{ + int32 index; + status_t result = B_BAD_VALUE, tmp; + + // protocols + PPPProtocol *protocol; + for(index = 0; index < CountProtocols(); index++) { + protocol = ProtocolAt(index); + if(!protocol) + break; + + tmp = protocol->Control(op, data, length); + if(tmp == B_OK && result == B_BAD_VALUE) + result = B_OK; + else if(tmp != B_BAD_VALUE) + result = tmp; + } + + // encapsulators + PPPEncapsulator *encapsulator = FirstEncapsulator(); + for(; encapsulator; encapsulator = encapsulator->Next()) { + tmp = encapsulator->Control(op, data, length); + if(tmp == B_OK && result == B_BAD_VALUE) + result = B_OK; + else if(tmp != B_BAD_VALUE) + result = tmp; + } + + // option handlers + PPPOptionHandler *optionHandler; + for(index = 0; index < LCP().CountOptionHandlers(); index++) { + optionHandler = LCP().OptionHandlerAt(index); + if(!optionHandler) + break; + + tmp = optionHandler->Control(op, data, length); + if(tmp == B_OK && result == B_BAD_VALUE) + result = B_OK; + else if(tmp != B_BAD_VALUE) + result = tmp; + } + + // LCP extensions + PPPLCPExtension *lcpExtension; + for(index = 0; index < LCP().CountLCPExtensions(); index++) { + lcpExtension = LCP().LCPExtensionAt(index); + if(!lcpExtension) + break; + + tmp = lcpExtension->Control(op, data, length); + if(tmp == B_OK && result == B_BAD_VALUE) + result = B_OK; + else if(tmp != B_BAD_VALUE) + result = tmp; + } + + return result; +} + + void PPPInterface::CalculateInterfaceMTU() { @@ -1446,8 +1621,11 @@ redial_thread(void *data) receive_data(&sender, &info, sizeof(redial_info)); // we try to receive data instead of snooze, so we can quit on destruction - if(receive_data_with_timeout(&sender, &code, NULL, 0, info.delay) == B_OK) + if(receive_data_with_timeout(&sender, &code, NULL, 0, info.delay) == B_OK) { + *info.thread = -1; + info.interface->Report(PPP_CONNECTION_REPORT, PPP_REPORT_UP_ABORTED, NULL, 0); return B_OK; + } info.interface->Up(); *info.thread = -1; diff --git a/src/tests/kits/net/ppp/src/KPPPLCP.cpp b/src/tests/kits/net/ppp/src/KPPPLCP.cpp index e9e85f9714..3fb4da226b 100644 --- a/src/tests/kits/net/ppp/src/KPPPLCP.cpp +++ b/src/tests/kits/net/ppp/src/KPPPLCP.cpp @@ -24,7 +24,8 @@ PPPLCP::PPPLCP(PPPInterface& interface) : PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL, AF_UNSPEC, interface, NULL, PPP_ALWAYS_ALLOWED), - fStateMachine(interface.StateMachine()), fTarget(NULL) + fStateMachine(interface.StateMachine()), + fTarget(NULL) { SetUpRequested(false); // the state machine does everything for us diff --git a/src/tests/kits/net/ppp/src/KPPPLCPExtension.cpp b/src/tests/kits/net/ppp/src/KPPPLCPExtension.cpp index 4951f54ba0..800c438077 100644 --- a/src/tests/kits/net/ppp/src/KPPPLCPExtension.cpp +++ b/src/tests/kits/net/ppp/src/KPPPLCPExtension.cpp @@ -12,7 +12,10 @@ PPPLCPExtension::PPPLCPExtension(const char *name, uint8 code, PPPInterface& interface, driver_parameter *settings) - : fInterface(interface), fSettings(settings), fCode(code), fEnabled(true) + : fInterface(interface), + fSettings(settings), + fCode(code), + fEnabled(true) { if(name) { strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); @@ -33,9 +36,6 @@ PPPLCPExtension::~PPPLCPExtension() status_t PPPLCPExtension::InitCheck() const { - if(!Settings()) - return B_ERROR; - return fInitStatus; } @@ -63,7 +63,7 @@ PPPLCPExtension::Control(uint32 op, void *data, size_t length) break; default: - return PPP_UNHANDLED; + return B_BAD_VALUE; } return B_OK; diff --git a/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp b/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp index 79618ea209..0a768af341 100644 --- a/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp +++ b/src/tests/kits/net/ppp/src/KPPPOptionHandler.cpp @@ -12,7 +12,10 @@ PPPOptionHandler::PPPOptionHandler(const char *name, uint8 type, PPPInterface& interface, driver_parameter *settings) - : fType(type), fInterface(interface), fSettings(settings), fEnabled(true) + : fType(type), + fInterface(interface), + fSettings(settings), + fEnabled(true) { if(name) { strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); @@ -33,9 +36,6 @@ PPPOptionHandler::~PPPOptionHandler() status_t PPPOptionHandler::InitCheck() const { - if(!Settings()) - return B_ERROR; - return fInitStatus; } @@ -63,7 +63,7 @@ PPPOptionHandler::Control(uint32 op, void *data, size_t length) break; default: - return PPP_UNHANDLED; + return B_BAD_VALUE; } return B_OK; diff --git a/src/tests/kits/net/ppp/src/KPPPProtocol.cpp b/src/tests/kits/net/ppp/src/KPPPProtocol.cpp index ba78c555de..693eb93bc8 100644 --- a/src/tests/kits/net/ppp/src/KPPPProtocol.cpp +++ b/src/tests/kits/net/ppp/src/KPPPProtocol.cpp @@ -16,10 +16,16 @@ PPPProtocol::PPPProtocol(const char *name, ppp_phase phase, uint16 protocol, int32 addressFamily, PPPInterface& interface, driver_parameter *settings, int32 flags = PPP_NO_FLAGS, ppp_authenticator_type authenticatorType = PPP_NO_AUTHENTICATOR) - : fPhase(phase), fProtocol(protocol), fAddressFamily(addressFamily), - fInterface(interface), fSettings(settings), fFlags(flags), - fAuthenticatorType(authenticatorType), fEnabled(true), - fUpRequested(true), fConnectionStatus(PPP_DOWN_PHASE) + : fPhase(phase), + fProtocol(protocol), + fAddressFamily(addressFamily), + fInterface(interface), + fSettings(settings), + fFlags(flags), + fAuthenticatorType(authenticatorType), + fEnabled(true), + fUpRequested(true), + fConnectionStatus(PPP_DOWN_PHASE) { if(name) { strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); @@ -44,9 +50,6 @@ PPPProtocol::~PPPProtocol() status_t PPPProtocol::InitCheck() const { - if(!Settings()) - return B_ERROR; - return fInitStatus; } @@ -94,7 +97,7 @@ PPPProtocol::Control(uint32 op, void *data, size_t length) break; default: - return PPP_UNHANDLED; + return B_BAD_VALUE; } return B_OK; diff --git a/src/tests/kits/net/ppp/src/KPPPReportManager.cpp b/src/tests/kits/net/ppp/src/KPPPReportManager.cpp index be4642fc93..2a03c69dfb 100644 --- a/src/tests/kits/net/ppp/src/KPPPReportManager.cpp +++ b/src/tests/kits/net/ppp/src/KPPPReportManager.cpp @@ -93,7 +93,7 @@ PPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 len LockerHelper locker(fLock); status_t result; - thread_id sender; + thread_id sender, me = find_thread(NULL); bool acceptable = true; ppp_report_packet report; @@ -107,6 +107,10 @@ PPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 len for(int32 index = 0; index < fReportRequests.CountItems(); index++) { request = fReportRequests.ItemAt(index); + // do not send to yourself + if(request->thread == me) + continue; + result = send_data_with_timeout(request->thread, PPP_REPORT_CODE, &report, sizeof(report), PPP_REPORT_TIMEOUT); diff --git a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp index 5476b43cf5..0255c3df39 100644 --- a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp +++ b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp @@ -22,20 +22,30 @@ PPPStateMachine::PPPStateMachine(PPPInterface& interface) - : fInterface(interface), fLCP(interface.LCP()), fPhase(PPP_DOWN_PHASE), - fState(PPP_INITIAL_STATE), fID(system_time() & 0xFF), fMagicNumber(0), - fAuthenticationStatus(PPP_NOT_AUTHENTICATED), + : fInterface(interface), + fLCP(interface.LCP()), + fPhase(PPP_DOWN_PHASE), + fState(PPP_INITIAL_STATE), + fID(system_time() & 0xFF), + fMagicNumber(0), + fLocalAuthenticationStatus(PPP_NOT_AUTHENTICATED), fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED), - fAuthenticationName(NULL), fPeerAuthenticationName(NULL), - fMaxRequest(10), fMaxTerminate(2), fMaxNak(5), - fRequestID(0), fTerminateID(0), fEchoID(0), fNextTimeout(0) + fLocalAuthenticationName(NULL), + fPeerAuthenticationName(NULL), + fMaxRequest(10), + fMaxTerminate(2), + fMaxNak(5), + fRequestID(0), + fTerminateID(0), + fEchoID(0), + fNextTimeout(0) { } PPPStateMachine::~PPPStateMachine() { - free(fAuthenticationName); + free(fLocalAuthenticationName); free(fPeerAuthenticationName); } @@ -169,38 +179,38 @@ PPPStateMachine::SendDiscardRequest() // authentication events void -PPPStateMachine::AuthenticationRequested() +PPPStateMachine::LocalAuthenticationRequested() { LockerHelper locker(fLock); - fAuthenticationStatus = PPP_AUTHENTICATING; - free(fAuthenticationName); - fAuthenticationName = NULL; + fLocalAuthenticationStatus = PPP_AUTHENTICATING; + free(fLocalAuthenticationName); + fLocalAuthenticationName = NULL; } void -PPPStateMachine::AuthenticationAccepted(const char *name) +PPPStateMachine::LocalAuthenticationAccepted(const char *name) { LockerHelper locker(fLock); - fAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL; - free(fAuthenticationName); - fAuthenticationName = strdup(name); + fLocalAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL; + free(fLocalAuthenticationName); + fLocalAuthenticationName = strdup(name); - Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_AUTHENTICATION_SUCCESSFUL, - NULL, 0); + Interface().Report(PPP_CONNECTION_REPORT, + PPP_REPORT_LOCAL_AUTHENTICATION_SUCCESSFUL, NULL, 0); } void -PPPStateMachine::AuthenticationDenied(const char *name) +PPPStateMachine::LocalAuthenticationDenied(const char *name) { LockerHelper locker(fLock); - fAuthenticationStatus = PPP_AUTHENTICATION_FAILED; - free(fAuthenticationName); - fAuthenticationName = strdup(name); + fLocalAuthenticationStatus = PPP_AUTHENTICATION_FAILED; + free(fLocalAuthenticationName); + fLocalAuthenticationName = strdup(name); } @@ -469,7 +479,7 @@ PPPStateMachine::UpEvent() switch(State()) { case PPP_INITIAL_STATE: if(Interface().Mode() != PPP_SERVER_MODE - || Phase() != PPP_ESTABLISHMENT_PHASE) { + || Phase() != PPP_ESTABLISHMENT_PHASE) { // we are a client or we do not listen for an incoming // connection, so this is an illegal event IllegalEvent(PPP_UP_EVENT); @@ -550,24 +560,26 @@ PPPStateMachine::DownEvent() IllegalEvent(PPP_DOWN_EVENT); } + NewPhase(PPP_DOWN_PHASE); + DownProtocols(); DownEncapsulators(); - fAuthenticationStatus = PPP_NOT_AUTHENTICATED; + fLocalAuthenticationStatus = PPP_NOT_AUTHENTICATED; fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED; - NewPhase(PPP_DOWN_PHASE); - // maybe we need to redial if(State() == PPP_STARTING_STATE) { bool needsRedial = false; - if(fAuthenticationStatus == PPP_AUTHENTICATION_FAILED - || fAuthenticationStatus == PPP_AUTHENTICATING - || fPeerAuthenticationStatus == PPP_AUTHENTICATION_FAILED + if(fLocalAuthenticationStatus == PPP_AUTHENTICATION_FAILED + || fLocalAuthenticationStatus == PPP_AUTHENTICATING) + Interface().Report(PPP_CONNECTION_REPORT, + PPP_REPORT_LOCAL_AUTHENTICATION_FAILED, NULL, 0); + else if(fPeerAuthenticationStatus == PPP_AUTHENTICATION_FAILED || fPeerAuthenticationStatus == PPP_AUTHENTICATING) - Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_AUTHENTICATION_FAILED, - NULL, 0); + Interface().Report(PPP_CONNECTION_REPORT, + PPP_REPORT_PEER_AUTHENTICATION_FAILED, NULL, 0); else { // if we are going up and lost connection the redial attempt becomes // a dial retry which is managed by the main thread in Interface::Up() @@ -671,15 +683,16 @@ PPPStateMachine::CloseEvent() switch(State()) { case PPP_OPENED_STATE: - ThisLayerDown(); - case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: NewState(PPP_CLOSING_STATE); NewPhase(PPP_TERMINATION_PHASE); + // indicates to handlers that we are terminating InitializeRestartCount(); locker.UnlockNow(); + if(State() == PPP_OPENED_STATE) + ThisLayerDown(); SendTerminateRequest(); break; @@ -688,7 +701,7 @@ PPPStateMachine::CloseEvent() // TLSNotify() will know that we were faster because we // are in PPP_INITIAL_STATE now - if(Phase() == PPP_ESTABLISHMENT_PHASE && Interface().Parent()) { + if(Phase() == PPP_ESTABLISHMENT_PHASE) { // the device is already up NewPhase(PPP_DOWN_PHASE); // this says the following DownEvent() was not caused by @@ -903,7 +916,12 @@ PPPStateMachine::RCAEvent(struct mbuf *packet) PPPOptionHandler *handler; for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) { handler = LCP().OptionHandlerAt(index); - handler->ParseAck(&ack); + if(handler->ParseAck(ack) != B_OK) { + m_freem(packet); + locker.UnlockNow(); + CloseEvent(); + return; + } } switch(State()) { @@ -974,10 +992,21 @@ PPPStateMachine::RCNEvent(struct mbuf *packet) for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) { handler = LCP().OptionHandlerAt(index); - if(nak_reject.Code() == PPP_CONFIGURE_NAK) - handler->ParseNak(&nak_reject); - else if(nak_reject.Code() == PPP_CONFIGURE_REJECT) - handler->ParseReject(&nak_reject); + if(nak_reject.Code() == PPP_CONFIGURE_NAK) { + if(handler->ParseNak(nak_reject) != B_OK) { + m_freem(packet); + locker.UnlockNow(); + CloseEvent(); + return; + } + } else if(nak_reject.Code() == PPP_CONFIGURE_REJECT) { + if(handler->ParseReject(nak_reject) != B_OK) { + m_freem(packet); + locker.UnlockNow(); + CloseEvent(); + return; + } + } } switch(State()) { @@ -1030,7 +1059,7 @@ PPPStateMachine::RTREvent(struct mbuf *packet) if(fID == mtod(packet, ppp_lcp_packet*)->id) fID -= 128; - fAuthenticationStatus = PPP_NOT_AUTHENTICATED; + fLocalAuthenticationStatus = PPP_NOT_AUTHENTICATED; fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED; switch(State()) { @@ -1107,6 +1136,8 @@ PPPStateMachine::RTAEvent(struct mbuf *packet) case PPP_OPENED_STATE: NewState(PPP_REQ_SENT_STATE); + NewPhase(PPP_ESTABLISHMENT_PHASE); + // indicates to handlers that we are reconfiguring locker.UnlockNow(); ThisLayerDown(); SendConfigureRequest(); @@ -1185,12 +1216,14 @@ PPPStateMachine::RXJBadEvent(struct mbuf *packet) ThisLayerFinished(); break; - case PPP_STOPPING_STATE: case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: NewState(PPP_STOPPED_STATE); + case PPP_STOPPING_STATE: + NewPhase(PPP_TERMINATION_PHASE); + case PPP_STOPPED_STATE: locker.UnlockNow(); ThisLayerFinished(); @@ -1198,6 +1231,8 @@ PPPStateMachine::RXJBadEvent(struct mbuf *packet) case PPP_OPENED_STATE: NewState(PPP_STOPPING_STATE); + NewPhase(PPP_TERMINATION_PHASE); + // indicates to handlers that we are terminating InitializeRestartCount(); locker.UnlockNow(); ThisLayerDown(); @@ -1283,7 +1318,6 @@ PPPStateMachine::RCREvent(struct mbuf *packet) { PPPConfigurePacket request(packet), nak(PPP_CONFIGURE_NAK), reject(PPP_CONFIGURE_REJECT); - PPPOptionHandler *handler; // we should not use the same id as the peer if(fID == mtod(packet, ppp_lcp_packet*)->id) @@ -1293,34 +1327,46 @@ PPPStateMachine::RCREvent(struct mbuf *packet) reject.SetID(request.ID()); // each handler should add unacceptable values for each item - bool handled; - int32 error; - for(int32 item = 0; item <= request.CountItems(); item++) { - // if we sent too many naks we should not append additional values - if(fNakCounter == 0 && item == request.CountItems()) - break; + status_t result; + // the return value of ParseRequest() + PPPOptionHandler *handler; + for(int32 index = 0; index < request.CountItems(); index++) { + handler = LCP().OptionHandlerFor(request.ItemAt(index)->type); - handled = false; - - for(int32 index = 0; index < LCP().CountOptionHandlers(); - index++) { - handler = LCP().OptionHandlerAt(index); - error = handler->ParseRequest(&request, item, &nak, &reject); - if(error == PPP_UNHANDLED) - continue; - 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) - handled = true; + if(!handler || !handler->IsEnabled()) { + // unhandled items should be added to reject + reject.AddItem(request.ItemAt(index)); + continue; } - if(!handled && item < request.CountItems()) { - // unhandled items should be added to reject - reject.AddItem(request.ItemAt(item)); + result = handler->ParseRequest(request, index, nak, reject); + + if(result != B_OK && result != PPP_UNHANDLED) { + // the request contains a value that has been sent more than + // once or the value is corrupted + m_freem(packet); + CloseEvent(); + return; + } + } + + // Additional values may be appended. + // If we sent too many naks we should not append additional values. + if(fNakCounter > 0) { + for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) { + handler = LCP().OptionHandlerAt(index); + if(handler && handler->IsEnabled()) { + result = handler->ParseRequest(request, request.CountItems(), + nak, reject); + + if(result != B_OK && result != PPP_UNHANDLED) { + // the request contains a value that has been sent more than + // once or the value is corrupted + m_freem(packet); + CloseEvent(); + return; + } + } } } @@ -1498,7 +1544,7 @@ PPPStateMachine::SendConfigureRequest() for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) { // add all items - if(!LCP().OptionHandlerAt(index)->AddToRequest(&request)) { + if(LCP().OptionHandlerAt(index)->AddToRequest(request) != B_OK) { CloseEvent(); return false; } @@ -1518,8 +1564,13 @@ PPPStateMachine::SendConfigureAck(struct mbuf *packet) 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); + for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) { + if(LCP().OptionHandlerAt(index)->SendingAck(ack) != B_OK) { + m_freem(packet); + CloseEvent(); + return false; + } + } return LCP().Send(packet) == B_OK; } diff --git a/src/tests/kits/net/ppp/src/_KPPPPFCHandler.cpp b/src/tests/kits/net/ppp/src/_KPPPPFCHandler.cpp new file mode 100644 index 0000000000..f624f47301 --- /dev/null +++ b/src/tests/kits/net/ppp/src/_KPPPPFCHandler.cpp @@ -0,0 +1,120 @@ +//---------------------------------------------------------------------- +// 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 "_KPPPPFCHandler.h" + +#include + +#define PFC_TYPE 0x7 + + +_PPPPFCHandler::_PPPPFCHandler(ppp_pfc_state& localPFCState, + ppp_pfc_state& peerPFCState, PPPInterface& interface) + : PPPOptionHandler("PFC Handler", PFC_TYPE, interface, NULL), + fLocalPFCState(localPFCState), + fPeerPFCState(peerPFCState) +{ +} + + +status_t +_PPPPFCHandler::AddToRequest(PPPConfigurePacket& request) +{ + // is PFC not requested or was it rejected? + if(fLocalPFCState & PPP_PFC_REJECTED + || (Interface().PFCOptions() & PPP_REQUEST_PFC) == 0) + return B_OK; + + // add PFC request + ppp_configure_item item; + item.type = PFC_TYPE; + item.length = 2; + return request.AddItem(&item) ? B_OK : B_ERROR; +} + + +status_t +_PPPPFCHandler::ParseNak(const PPPConfigurePacket& nak) +{ + // naks do not contain PFC items + if(nak.ItemWithType(PFC_TYPE)) + return B_ERROR; + + return B_OK; +} + + +status_t +_PPPPFCHandler::ParseReject(const PPPConfigurePacket& reject) +{ + if(reject.ItemWithType(PFC_TYPE)) { + fLocalPFCState = PPP_PFC_REJECTED; + + if(Interface().PFCOptions() & PPP_FORCE_PFC_REQUEST) + return B_ERROR; + } + + return B_OK; +} + + +status_t +_PPPPFCHandler::ParseAck(const PPPConfigurePacket& ack) +{ + if(ack.ItemWithType(PFC_TYPE)) + fLocalPFCState = PPP_PFC_ACCEPTED; + else { + fLocalPFCState = PPP_PFC_DISABLED; + + if(Interface().PFCOptions() & PPP_FORCE_PFC_REQUEST) + return B_ERROR; + } + + return B_OK; +} + + +status_t +_PPPPFCHandler::ParseRequest(const PPPConfigurePacket& request, + int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject) +{ + if(!request.ItemWithType(PFC_TYPE)) + return B_OK; + + if((Interface().PFCOptions() & PPP_ALLOW_PFC) == 0) { + ppp_configure_item item; + item.type = PFC_TYPE; + item.length = 2; + return reject.AddItem(&item) ? B_OK : B_ERROR; + } + + return B_OK; +} + + +status_t +_PPPPFCHandler::SendingAck(const PPPConfigurePacket& ack) +{ + ppp_configure_item *item = ack.ItemWithType(PFC_TYPE); + + if(item && (Interface().PFCOptions() & PPP_ALLOW_PFC) == 0) + return B_ERROR; + + if(item) + fPeerPFCState = PPP_PFC_ACCEPTED; + else + fPeerPFCState = PPP_PFC_DISABLED; + + return B_OK; +} + + +void +_PPPPFCHandler::Reset() +{ + fLocalPFCState = fPeerPFCState = PPP_PFC_DISABLED; +} diff --git a/src/tests/kits/net/ppp/src/_KPPPPFCHandler.h b/src/tests/kits/net/ppp/src/_KPPPPFCHandler.h new file mode 100644 index 0000000000..c542ac3f2e --- /dev/null +++ b/src/tests/kits/net/ppp/src/_KPPPPFCHandler.h @@ -0,0 +1,35 @@ +//---------------------------------------------------------------------- +// 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_PFC_HANDLER__H +#define __K_PPP_PFC_HANDLER__H + +#include + + +class _PPPPFCHandler : public PPPOptionHandler { + public: + _PPPPFCHandler(ppp_pfc_state& localPFCState, ppp_pfc_state& peerPFCState, + PPPInterface& interface); + + virtual status_t AddToRequest(PPPConfigurePacket& request); + virtual status_t ParseNak(const PPPConfigurePacket& nak); + virtual status_t ParseReject(const PPPConfigurePacket& reject); + virtual status_t ParseAck(const PPPConfigurePacket& ack); + + virtual status_t ParseRequest(const PPPConfigurePacket& request, + int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject); + virtual status_t SendingAck(const PPPConfigurePacket& ack); + + virtual void Reset(); + + private: + ppp_pfc_state &fLocalPFCState, &fPeerPFCState; +}; + + +#endif