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