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
This commit is contained in:
Waldemar Kornewald 2003-09-13 17:57:12 +00:00
parent 6151971100
commit 7ff713dadd
23 changed files with 630 additions and 168 deletions

View File

@ -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 #ifndef _K_PPP__H
#define _K_PPP__H #define _K_PPP__H

View File

@ -79,11 +79,12 @@ class PPPDevice {
uint32 fMTU; uint32 fMTU;
bool fIsUp; bool fIsUp;
status_t fInitStatus;
private: private:
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
PPPInterface& fInterface; PPPInterface& fInterface;
driver_parameter *fSettings; driver_parameter *fSettings;
status_t fInitStatus;
}; };

View File

@ -100,6 +100,8 @@ class PPPEncapsulator {
protected: protected:
uint32 fOverhead; uint32 fOverhead;
status_t fInitStatus;
private: private:
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
ppp_phase fPhase; ppp_phase fPhase;
@ -115,7 +117,6 @@ class PPPEncapsulator {
bool fEnabled; bool fEnabled;
bool fUpRequested; bool fUpRequested;
ppp_phase fConnectionStatus; ppp_phase fConnectionStatus;
status_t fInitStatus;
}; };

View File

@ -141,6 +141,21 @@ class PPPInterface {
ppp_phase Phase() const ppp_phase Phase() const
{ return fStateMachine.Phase(); } { 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(); bool Up();
// in server mode Up() listens for an incoming connection // in server mode Up() listens for an incoming connection
bool Down(); bool Down();
@ -175,6 +190,11 @@ class PPPInterface {
// saves the returned ifnet structure // saves the returned ifnet structure
bool UnregisterInterface(); 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 CalculateInterfaceMTU();
void CalculateBaudRate(); void CalculateBaudRate();
@ -213,9 +233,9 @@ class PPPInterface {
bool fAutoRedial, fDialOnDemand; bool fAutoRedial, fDialOnDemand;
vint32 fAccesing;
ppp_mode fMode; ppp_mode fMode;
ppp_pfc_state fLocalPFCState, fPeerPFCState;
uint8 fPFCOptions;
PPPDevice *fDevice; PPPDevice *fDevice;
PPPEncapsulator *fFirstEncapsulator; PPPEncapsulator *fFirstEncapsulator;

View File

@ -41,12 +41,14 @@ class PPPLCPExtension {
virtual status_t Control(uint32 op, void *data, size_t length); 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 status_t Receive(struct mbuf *packet, uint8 code) = 0;
virtual void Reset();
virtual void Pulse(); virtual void Pulse();
protected:
status_t fInitStatus;
private: private:
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
PPPInterface& fInterface; PPPInterface& fInterface;
@ -54,7 +56,6 @@ class PPPLCPExtension {
uint8 fCode; uint8 fCode;
bool fEnabled; bool fEnabled;
status_t fInitStatus;
}; };

View File

@ -43,26 +43,29 @@ class PPPOptionHandler {
virtual status_t Control(uint32 op, void *data, size_t length); 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 // we want to send a configure request or we received a reply
virtual status_t AddToRequest(PPPConfigurePacket *request) = 0; virtual status_t AddToRequest(PPPConfigurePacket& request) = 0;
virtual void ParseNak(const PPPConfigurePacket *nak) = 0; virtual status_t ParseNak(const PPPConfigurePacket& nak) = 0;
// create next request based on these and previous values // 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 // 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 // this is called for all handlers
// peer sent configure request // peer sent configure request
virtual status_t ParseRequest(const PPPConfigurePacket *request, virtual status_t ParseRequest(const PPPConfigurePacket& request,
int32 item, PPPConfigurePacket *nak, PPPConfigurePacket *reject) = 0; int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject) = 0;
// item may be behind the last item which means we can add // index may be behind the last item which means additional values can be
// additional values // appended
virtual void SendingAck(const PPPConfigurePacket *ack) = 0; virtual status_t SendingAck(const PPPConfigurePacket& ack) = 0;
// notification that we ack these values // notification that we ack these values
virtual void Reset() = 0;
// e.g.: remove list of rejected values
protected:
status_t fInitStatus;
private: private:
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
uint8 fType; uint8 fType;
@ -70,7 +73,6 @@ class PPPOptionHandler {
driver_parameter *fSettings; driver_parameter *fSettings;
bool fEnabled; bool fEnabled;
status_t fInitStatus;
}; };

View File

@ -90,6 +90,9 @@ class PPPProtocol {
void DownEvent(); void DownEvent();
// report up/down events // report up/down events
protected:
status_t fInitStatus;
private: private:
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
ppp_phase fPhase; ppp_phase fPhase;
@ -103,7 +106,6 @@ class PPPProtocol {
bool fEnabled; bool fEnabled;
bool fUpRequested; bool fUpRequested;
ppp_phase fConnectionStatus; ppp_phase fConnectionStatus;
status_t fInitStatus;
}; };

View File

@ -58,13 +58,13 @@ class PPPStateMachine {
bool SendDiscardRequest(); bool SendDiscardRequest();
// public events // public events
void AuthenticationRequested(); void LocalAuthenticationRequested();
void AuthenticationAccepted(const char *name); void LocalAuthenticationAccepted(const char *name);
void AuthenticationDenied(const char *name); void LocalAuthenticationDenied(const char *name);
const char *AuthenticationName() const const char *LocalAuthenticationName() const
{ return fAuthenticationName; } { return fLocalAuthenticationName; }
ppp_authentication_status AuthenticationStatus() const ppp_authentication_status LocalAuthenticationStatus() const
{ return fAuthenticationStatus; } { return fLocalAuthenticationStatus; }
void PeerAuthenticationRequested(); void PeerAuthenticationRequested();
void PeerAuthenticationAccepted(const char *name); void PeerAuthenticationAccepted(const char *name);
@ -159,9 +159,9 @@ class PPPStateMachine {
vint32 fID; vint32 fID;
uint32 fMagicNumber; uint32 fMagicNumber;
ppp_authentication_status fAuthenticationStatus, ppp_authentication_status fLocalAuthenticationStatus,
fPeerAuthenticationStatus; fPeerAuthenticationStatus;
char *fAuthenticationName, *fPeerAuthenticationName; char *fLocalAuthenticationName, *fPeerAuthenticationName;
BLocker fLock; BLocker fLock;

View File

@ -59,6 +59,10 @@ enum ppp_control_ops {
PPPC_SET_ENABLED, PPPC_SET_ENABLED,
PPPC_GET_SIMPLE_HANDLER_INFO, PPPC_GET_SIMPLE_HANDLER_INFO,
// PPPOptionHandler and PPPLCPExtension // 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 PPP_CONTROL_OPS_END = B_DEVICE_OP_CODES_END + 0xFFFF
@ -89,13 +93,17 @@ typedef struct ppp_interface_info {
ppp_mode mode; ppp_mode mode;
ppp_state state; ppp_state state;
ppp_phase phase; ppp_phase phase;
ppp_authentication_status authenticationStatus, peerAuthenticationStatus; ppp_authentication_status localAuthenticationStatus, peerAuthenticationStatus;
ppp_pfc_state localPFCState, peerPFCState;
uint8 pfcOptions;
uint32 protocolsCount, encapsulatorsCount, optionHandlersCount, uint32 protocolsCount, encapsulatorsCount, optionHandlersCount,
LCPExtensionsCount, childrenCount; LCPExtensionsCount, childrenCount;
uint32 MRU, interfaceMTU; uint32 MRU, interfaceMTU;
bigtime_t idleSince, disconnectAfterIdleSince; uint32 dialRetry, dialRetriesLimit;
uint32 dialRetryDelay, redialDelay;
uint32 idleSince, disconnectAfterIdleSince;
bool doesDialOnDemand, doesAutoRedial, hasDevice, isMultilink, hasParent; bool doesDialOnDemand, doesAutoRedial, hasDevice, isMultilink, hasParent;
} ppp_interface_info; } ppp_interface_info;

View File

@ -62,6 +62,25 @@ enum {
// could not send a packet because device is not connected // 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 // protocol and encapsulator flags
enum { enum {
PPP_NO_FLAGS = 0x00, PPP_NO_FLAGS = 0x00,
@ -100,7 +119,8 @@ enum ppp_phase {
// this defines the order in which the packets get encapsulated // this defines the order in which the packets get encapsulated
enum ppp_encapsulation_level { enum ppp_encapsulation_level {
PPP_MULTILINK_LEVEL = 0, PPP_DEVICE_LEVEL = 0,
PPP_MULTILINK_LEVEL = 2,
PPP_ENCRYPTION_LEVEL = 5, PPP_ENCRYPTION_LEVEL = 5,
PPP_COMPRESSION_LEVEL = 10 PPP_COMPRESSION_LEVEL = 10
}; };

View File

@ -41,10 +41,11 @@ enum ppp_connection_report_codes {
PPP_REPORT_DOWN_SUCCESSFUL = 2, PPP_REPORT_DOWN_SUCCESSFUL = 2,
PPP_REPORT_UP_ABORTED = 3, PPP_REPORT_UP_ABORTED = 3,
PPP_REPORT_DEVICE_UP_FAILED = 4, 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_PEER_AUTHENTICATION_SUCCESSFUL = 6,
PPP_REPORT_AUTHENTICATION_FAILED = 7, PPP_REPORT_LOCAL_AUTHENTICATION_FAILED = 7,
PPP_REPORT_CONNECTION_LOST = 8 PPP_REPORT_PEER_AUTHENTICATION_FAILED = 8,
PPP_REPORT_CONNECTION_LOST = 9
}; };

View File

@ -23,5 +23,8 @@ R5KernelStaticLibrary kernelppp :
Locker.cpp Locker.cpp
settings_tools.cpp settings_tools.cpp
cpp.cpp cpp.cpp
# integrated modules
_KPPPPFCHandler.cpp
; ;

View File

@ -15,7 +15,10 @@
PPPDevice::PPPDevice(const char *name, PPPInterface& interface, PPPDevice::PPPDevice(const char *name, PPPInterface& interface,
driver_parameter *settings) driver_parameter *settings)
: fMTU(1500), fIsUp(false), fInterface(interface), fSettings(settings) : fMTU(1500),
fIsUp(false),
fInterface(interface),
fSettings(settings)
{ {
if(name) { if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
@ -36,9 +39,6 @@ PPPDevice::~PPPDevice()
status_t status_t
PPPDevice::InitCheck() const PPPDevice::InitCheck() const
{ {
if(!Settings())
return B_ERROR;
return fInitStatus; return fInitStatus;
} }
@ -63,7 +63,7 @@ PPPDevice::Control(uint32 op, void *data, size_t length)
} break; } break;
default: default:
return PPP_UNHANDLED; return B_BAD_VALUE;
} }
return B_OK; return B_OK;

View File

@ -16,10 +16,17 @@ PPPEncapsulator::PPPEncapsulator(const char *name, ppp_phase phase,
int32 addressFamily, uint32 overhead, int32 addressFamily, uint32 overhead,
PPPInterface& interface, driver_parameter *settings, PPPInterface& interface, driver_parameter *settings,
int32 flags = PPP_NO_FLAGS) int32 flags = PPP_NO_FLAGS)
: fOverhead(overhead), fPhase(phase), fLevel(level), fProtocol(protocol), : fOverhead(overhead),
fAddressFamily(addressFamily), fInterface(interface), fPhase(phase),
fSettings(settings), fFlags(flags), fEnabled(true), fLevel(level),
fUpRequested(true), fConnectionStatus(PPP_DOWN_PHASE) fProtocol(protocol),
fAddressFamily(addressFamily),
fInterface(interface),
fSettings(settings),
fFlags(flags),
fEnabled(true),
fUpRequested(true),
fConnectionStatus(PPP_DOWN_PHASE)
{ {
if(name) { if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
@ -40,9 +47,6 @@ PPPEncapsulator::~PPPEncapsulator()
status_t status_t
PPPEncapsulator::InitCheck() const PPPEncapsulator::InitCheck() const
{ {
if(!Settings())
return B_ERROR;
return fInitStatus; return fInitStatus;
} }
@ -91,7 +95,7 @@ PPPEncapsulator::Control(uint32 op, void *data, size_t length)
break; break;
default: default:
return PPP_UNHANDLED; return B_BAD_VALUE;
} }
return B_OK; return B_OK;

View File

@ -19,6 +19,7 @@
#include <PPPControl.h> #include <PPPControl.h>
#include <KPPPDevice.h> #include <KPPPDevice.h>
#include <KPPPEncapsulator.h> #include <KPPPEncapsulator.h>
#include <KPPPLCPExtension.h>
#include <KPPPOptionHandler.h> #include <KPPPOptionHandler.h>
#include <KPPPModule.h> #include <KPPPModule.h>
#include <KPPPManager.h> #include <KPPPManager.h>
@ -30,6 +31,9 @@
// tools only for us :) // tools only for us :)
#include "settings_tools.h" #include "settings_tools.h"
// internal modules
#include "_KPPPPFCHandler.h"
// TODO: // TODO:
// - implement timers with support for settings next time instead of receiving timer // - 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::PPPInterface(uint32 ID, driver_settings *settings,
PPPInterface *parent = NULL) PPPInterface *parent = NULL)
: fID(ID), fSettings(dup_driver_settings(settings)), : fID(ID),
fStateMachine(*this), fLCP(*this), fReportManager(StateMachine().Locker()), fSettings(dup_driver_settings(settings)),
fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0), fStateMachine(*this),
fDialRetriesLimit(0), fIdleSince(0), fMRU(1500), fInterfaceMTU(1498), fLCP(*this),
fHeaderLength(2), fAutoRedial(false), fDialOnDemand(false), fDevice(NULL), fReportManager(StateMachine().Locker()),
fFirstEncapsulator(NULL), fLock(StateMachine().Locker()), fDeleteCounter(0) 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 // set up dial delays
fDialRetryDelay = 3000; fDialRetryDelay = 3000;
// 3s delay between each new attempt to redial // 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->mode = Mode();
info->state = State(); info->state = State();
info->phase = Phase(); info->phase = Phase();
info->authenticationStatus = StateMachine().AuthenticationStatus(); info->localAuthenticationStatus =
StateMachine().LocalAuthenticationStatus();
info->peerAuthenticationStatus = info->peerAuthenticationStatus =
StateMachine().PeerAuthenticationStatus(); StateMachine().PeerAuthenticationStatus();
info->localPFCState = LocalPFCState();
info->peerPFCState = PeerPFCState();
info->pfcOptions = PFCOptions();
info->protocolsCount = CountProtocols(); info->protocolsCount = CountProtocols();
info->encapsulatorsCount = CountEncapsulators(); info->encapsulatorsCount = CountEncapsulators();
info->optionHandlersCount = LCP().CountOptionHandlers(); info->optionHandlersCount = LCP().CountOptionHandlers();
@ -263,6 +294,10 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
info->childrenCount = CountChildren(); info->childrenCount = CountChildren();
info->MRU = MRU(); info->MRU = MRU();
info->interfaceMTU = InterfaceMTU(); info->interfaceMTU = InterfaceMTU();
info->dialRetry = fDialRetry;
info->dialRetriesLimit = fDialRetriesLimit;
info->dialRetryDelay = DialRetryDelay();
info->redialDelay = RedialDelay();
info->idleSince = IdleSince(); info->idleSince = IdleSince();
info->disconnectAfterIdleSince = DisconnectAfterIdleSince(); info->disconnectAfterIdleSince = DisconnectAfterIdleSince();
info->doesDialOnDemand = DoesDialOnDemand(); info->doesDialOnDemand = DoesDialOnDemand();
@ -361,7 +396,16 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
} break; } break;
case PPPC_CONTROL_LCP_EXTENSION: { 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; } break;
case PPPC_CONTROL_CHILD: { 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); return child->Control(control->op, control->data, control->length);
} break; } 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: default:
return PPP_UNHANDLED; return B_BAD_VALUE;
} }
return B_OK; 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 bool
PPPInterface::Up() PPPInterface::Up()
{ {
@ -742,9 +808,13 @@ PPPInterface::Up()
fLock.Unlock(); fLock.Unlock();
// fUpThread tells the state machine to go up // fUpThread tells the state machine to go up
if(me == fUpThread) if(me == fUpThread || me == fRedialThread)
StateMachine().OpenEvent(); StateMachine().OpenEvent();
if(me == fRedialThread && me != fUpThread)
return true;
// the redial thread is doing a DialRetry in this case
while(true) { while(true) {
if(IsUp()) { if(IsUp()) {
// lock needs timeout because destructor could have locked the interface // lock needs timeout because destructor could have locked the interface
@ -763,6 +833,9 @@ PPPInterface::Up()
return true; 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) if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE)
continue; continue;
@ -798,6 +871,8 @@ PPPInterface::Up()
if(me == fUpThread) { if(me == fUpThread) {
fDialRetry = 0; fDialRetry = 0;
fUpThread = -1; 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); PPP_REPLY(sender, B_OK);
@ -805,7 +880,8 @@ PPPInterface::Up()
return true; return true;
} else if(report.code == PPP_REPORT_DOWN_SUCCESSFUL } else if(report.code == PPP_REPORT_DOWN_SUCCESSFUL
|| report.code == PPP_REPORT_UP_ABORTED || 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) { if(me == fUpThread) {
fDialRetry = 0; fDialRetry = 0;
fUpThread = -1; fUpThread = -1;
@ -857,7 +933,7 @@ PPPInterface::Up()
} else { } else {
++fDialRetry; ++fDialRetry;
PPP_REPLY(sender, B_OK); PPP_REPLY(sender, B_OK);
StateMachine().OpenEvent(); Redial(DialRetryDelay());
continue; continue;
} }
} else if(report.code == PPP_REPORT_CONNECTION_LOST) { } else if(report.code == PPP_REPORT_CONNECTION_LOST) {
@ -866,7 +942,7 @@ PPPInterface::Up()
if(DoesAutoRedial() && fDialRetry < fDialRetriesLimit) { if(DoesAutoRedial() && fDialRetry < fDialRetriesLimit) {
++fDialRetry; ++fDialRetry;
PPP_REPLY(sender, B_OK); PPP_REPLY(sender, B_OK);
StateMachine().OpenEvent(); Redial(DialRetryDelay());
continue; continue;
} else { } else {
fDialRetry = 0; fDialRetry = 0;
@ -897,6 +973,9 @@ PPPInterface::Down()
if(InitCheck() != B_OK) if(InitCheck() != B_OK)
return false; 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 // this locked section guarantees that there are no state changes before we
// enable the connection reports // enable the connection reports
LockerHelper locker(fLock); LockerHelper locker(fLock);
@ -1218,16 +1297,26 @@ PPPInterface::SendToDevice(struct mbuf *packet, uint16 protocol)
return B_ERROR; return B_ERROR;
} }
// encode in ppp frame // encode in ppp frame and consider using PFC
M_PREPEND(packet, 2); if(UseLocalPFC() && protocol & 0xFF00 == 0) {
M_PREPEND(packet, 1);
if(packet == NULL) if(packet == NULL)
return B_ERROR; return B_ERROR;
// set protocol (the only header field) uint8 *header = mtod(packet, uint8*);
protocol = htons(protocol); *header = protocol & 0xFF;
uint16 *header = mtod(packet, uint16*); } else {
*header = protocol; 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(); fIdleSince = real_time_clock();
@ -1260,13 +1349,16 @@ PPPInterface::ReceiveFromDevice(struct mbuf *packet)
return B_ERROR; return B_ERROR;
} }
// decode ppp frame // decode ppp frame and recognize PFC
uint16 *protocol = mtod(packet, uint16*); uint16 protocol = *mtod(packet, uint8*);
*protocol = ntohs(*protocol); 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 void
PPPInterface::CalculateInterfaceMTU() PPPInterface::CalculateInterfaceMTU()
{ {
@ -1446,8 +1621,11 @@ redial_thread(void *data)
receive_data(&sender, &info, sizeof(redial_info)); receive_data(&sender, &info, sizeof(redial_info));
// we try to receive data instead of snooze, so we can quit on destruction // 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; return B_OK;
}
info.interface->Up(); info.interface->Up();
*info.thread = -1; *info.thread = -1;

View File

@ -24,7 +24,8 @@
PPPLCP::PPPLCP(PPPInterface& interface) PPPLCP::PPPLCP(PPPInterface& interface)
: PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL, : PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL,
AF_UNSPEC, interface, NULL, PPP_ALWAYS_ALLOWED), AF_UNSPEC, interface, NULL, PPP_ALWAYS_ALLOWED),
fStateMachine(interface.StateMachine()), fTarget(NULL) fStateMachine(interface.StateMachine()),
fTarget(NULL)
{ {
SetUpRequested(false); SetUpRequested(false);
// the state machine does everything for us // the state machine does everything for us

View File

@ -12,7 +12,10 @@
PPPLCPExtension::PPPLCPExtension(const char *name, uint8 code, PPPInterface& interface, PPPLCPExtension::PPPLCPExtension(const char *name, uint8 code, PPPInterface& interface,
driver_parameter *settings) driver_parameter *settings)
: fInterface(interface), fSettings(settings), fCode(code), fEnabled(true) : fInterface(interface),
fSettings(settings),
fCode(code),
fEnabled(true)
{ {
if(name) { if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
@ -33,9 +36,6 @@ PPPLCPExtension::~PPPLCPExtension()
status_t status_t
PPPLCPExtension::InitCheck() const PPPLCPExtension::InitCheck() const
{ {
if(!Settings())
return B_ERROR;
return fInitStatus; return fInitStatus;
} }
@ -63,7 +63,7 @@ PPPLCPExtension::Control(uint32 op, void *data, size_t length)
break; break;
default: default:
return PPP_UNHANDLED; return B_BAD_VALUE;
} }
return B_OK; return B_OK;

View File

@ -12,7 +12,10 @@
PPPOptionHandler::PPPOptionHandler(const char *name, uint8 type, PPPOptionHandler::PPPOptionHandler(const char *name, uint8 type,
PPPInterface& interface, driver_parameter *settings) PPPInterface& interface, driver_parameter *settings)
: fType(type), fInterface(interface), fSettings(settings), fEnabled(true) : fType(type),
fInterface(interface),
fSettings(settings),
fEnabled(true)
{ {
if(name) { if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
@ -33,9 +36,6 @@ PPPOptionHandler::~PPPOptionHandler()
status_t status_t
PPPOptionHandler::InitCheck() const PPPOptionHandler::InitCheck() const
{ {
if(!Settings())
return B_ERROR;
return fInitStatus; return fInitStatus;
} }
@ -63,7 +63,7 @@ PPPOptionHandler::Control(uint32 op, void *data, size_t length)
break; break;
default: default:
return PPP_UNHANDLED; return B_BAD_VALUE;
} }
return B_OK; return B_OK;

View File

@ -16,10 +16,16 @@ PPPProtocol::PPPProtocol(const char *name, ppp_phase phase, uint16 protocol,
int32 addressFamily, PPPInterface& interface, int32 addressFamily, PPPInterface& interface,
driver_parameter *settings, int32 flags = PPP_NO_FLAGS, driver_parameter *settings, int32 flags = PPP_NO_FLAGS,
ppp_authenticator_type authenticatorType = PPP_NO_AUTHENTICATOR) ppp_authenticator_type authenticatorType = PPP_NO_AUTHENTICATOR)
: fPhase(phase), fProtocol(protocol), fAddressFamily(addressFamily), : fPhase(phase),
fInterface(interface), fSettings(settings), fFlags(flags), fProtocol(protocol),
fAuthenticatorType(authenticatorType), fEnabled(true), fAddressFamily(addressFamily),
fUpRequested(true), fConnectionStatus(PPP_DOWN_PHASE) fInterface(interface),
fSettings(settings),
fFlags(flags),
fAuthenticatorType(authenticatorType),
fEnabled(true),
fUpRequested(true),
fConnectionStatus(PPP_DOWN_PHASE)
{ {
if(name) { if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
@ -44,9 +50,6 @@ PPPProtocol::~PPPProtocol()
status_t status_t
PPPProtocol::InitCheck() const PPPProtocol::InitCheck() const
{ {
if(!Settings())
return B_ERROR;
return fInitStatus; return fInitStatus;
} }
@ -94,7 +97,7 @@ PPPProtocol::Control(uint32 op, void *data, size_t length)
break; break;
default: default:
return PPP_UNHANDLED; return B_BAD_VALUE;
} }
return B_OK; return B_OK;

View File

@ -93,7 +93,7 @@ PPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 len
LockerHelper locker(fLock); LockerHelper locker(fLock);
status_t result; status_t result;
thread_id sender; thread_id sender, me = find_thread(NULL);
bool acceptable = true; bool acceptable = true;
ppp_report_packet report; 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++) { for(int32 index = 0; index < fReportRequests.CountItems(); index++) {
request = fReportRequests.ItemAt(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, result = send_data_with_timeout(request->thread, PPP_REPORT_CODE, &report,
sizeof(report), PPP_REPORT_TIMEOUT); sizeof(report), PPP_REPORT_TIMEOUT);

View File

@ -22,20 +22,30 @@
PPPStateMachine::PPPStateMachine(PPPInterface& interface) PPPStateMachine::PPPStateMachine(PPPInterface& interface)
: fInterface(interface), fLCP(interface.LCP()), fPhase(PPP_DOWN_PHASE), : fInterface(interface),
fState(PPP_INITIAL_STATE), fID(system_time() & 0xFF), fMagicNumber(0), fLCP(interface.LCP()),
fAuthenticationStatus(PPP_NOT_AUTHENTICATED), fPhase(PPP_DOWN_PHASE),
fState(PPP_INITIAL_STATE),
fID(system_time() & 0xFF),
fMagicNumber(0),
fLocalAuthenticationStatus(PPP_NOT_AUTHENTICATED),
fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED), fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED),
fAuthenticationName(NULL), fPeerAuthenticationName(NULL), fLocalAuthenticationName(NULL),
fMaxRequest(10), fMaxTerminate(2), fMaxNak(5), fPeerAuthenticationName(NULL),
fRequestID(0), fTerminateID(0), fEchoID(0), fNextTimeout(0) fMaxRequest(10),
fMaxTerminate(2),
fMaxNak(5),
fRequestID(0),
fTerminateID(0),
fEchoID(0),
fNextTimeout(0)
{ {
} }
PPPStateMachine::~PPPStateMachine() PPPStateMachine::~PPPStateMachine()
{ {
free(fAuthenticationName); free(fLocalAuthenticationName);
free(fPeerAuthenticationName); free(fPeerAuthenticationName);
} }
@ -169,38 +179,38 @@ PPPStateMachine::SendDiscardRequest()
// authentication events // authentication events
void void
PPPStateMachine::AuthenticationRequested() PPPStateMachine::LocalAuthenticationRequested()
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
fAuthenticationStatus = PPP_AUTHENTICATING; fLocalAuthenticationStatus = PPP_AUTHENTICATING;
free(fAuthenticationName); free(fLocalAuthenticationName);
fAuthenticationName = NULL; fLocalAuthenticationName = NULL;
} }
void void
PPPStateMachine::AuthenticationAccepted(const char *name) PPPStateMachine::LocalAuthenticationAccepted(const char *name)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
fAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL; fLocalAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL;
free(fAuthenticationName); free(fLocalAuthenticationName);
fAuthenticationName = strdup(name); fLocalAuthenticationName = strdup(name);
Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_AUTHENTICATION_SUCCESSFUL, Interface().Report(PPP_CONNECTION_REPORT,
NULL, 0); PPP_REPORT_LOCAL_AUTHENTICATION_SUCCESSFUL, NULL, 0);
} }
void void
PPPStateMachine::AuthenticationDenied(const char *name) PPPStateMachine::LocalAuthenticationDenied(const char *name)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
fAuthenticationStatus = PPP_AUTHENTICATION_FAILED; fLocalAuthenticationStatus = PPP_AUTHENTICATION_FAILED;
free(fAuthenticationName); free(fLocalAuthenticationName);
fAuthenticationName = strdup(name); fLocalAuthenticationName = strdup(name);
} }
@ -469,7 +479,7 @@ PPPStateMachine::UpEvent()
switch(State()) { switch(State()) {
case PPP_INITIAL_STATE: case PPP_INITIAL_STATE:
if(Interface().Mode() != PPP_SERVER_MODE 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 // we are a client or we do not listen for an incoming
// connection, so this is an illegal event // connection, so this is an illegal event
IllegalEvent(PPP_UP_EVENT); IllegalEvent(PPP_UP_EVENT);
@ -550,24 +560,26 @@ PPPStateMachine::DownEvent()
IllegalEvent(PPP_DOWN_EVENT); IllegalEvent(PPP_DOWN_EVENT);
} }
NewPhase(PPP_DOWN_PHASE);
DownProtocols(); DownProtocols();
DownEncapsulators(); DownEncapsulators();
fAuthenticationStatus = PPP_NOT_AUTHENTICATED; fLocalAuthenticationStatus = PPP_NOT_AUTHENTICATED;
fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED; fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED;
NewPhase(PPP_DOWN_PHASE);
// maybe we need to redial // maybe we need to redial
if(State() == PPP_STARTING_STATE) { if(State() == PPP_STARTING_STATE) {
bool needsRedial = false; bool needsRedial = false;
if(fAuthenticationStatus == PPP_AUTHENTICATION_FAILED if(fLocalAuthenticationStatus == PPP_AUTHENTICATION_FAILED
|| fAuthenticationStatus == PPP_AUTHENTICATING || fLocalAuthenticationStatus == PPP_AUTHENTICATING)
|| fPeerAuthenticationStatus == PPP_AUTHENTICATION_FAILED Interface().Report(PPP_CONNECTION_REPORT,
PPP_REPORT_LOCAL_AUTHENTICATION_FAILED, NULL, 0);
else if(fPeerAuthenticationStatus == PPP_AUTHENTICATION_FAILED
|| fPeerAuthenticationStatus == PPP_AUTHENTICATING) || fPeerAuthenticationStatus == PPP_AUTHENTICATING)
Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_AUTHENTICATION_FAILED, Interface().Report(PPP_CONNECTION_REPORT,
NULL, 0); PPP_REPORT_PEER_AUTHENTICATION_FAILED, NULL, 0);
else { else {
// if we are going up and lost connection the redial attempt becomes // 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() // a dial retry which is managed by the main thread in Interface::Up()
@ -671,15 +683,16 @@ PPPStateMachine::CloseEvent()
switch(State()) { switch(State()) {
case PPP_OPENED_STATE: case PPP_OPENED_STATE:
ThisLayerDown();
case PPP_REQ_SENT_STATE: case PPP_REQ_SENT_STATE:
case PPP_ACK_RCVD_STATE: case PPP_ACK_RCVD_STATE:
case PPP_ACK_SENT_STATE: case PPP_ACK_SENT_STATE:
NewState(PPP_CLOSING_STATE); NewState(PPP_CLOSING_STATE);
NewPhase(PPP_TERMINATION_PHASE); NewPhase(PPP_TERMINATION_PHASE);
// indicates to handlers that we are terminating
InitializeRestartCount(); InitializeRestartCount();
locker.UnlockNow(); locker.UnlockNow();
if(State() == PPP_OPENED_STATE)
ThisLayerDown();
SendTerminateRequest(); SendTerminateRequest();
break; break;
@ -688,7 +701,7 @@ PPPStateMachine::CloseEvent()
// TLSNotify() will know that we were faster because we // TLSNotify() will know that we were faster because we
// are in PPP_INITIAL_STATE now // are in PPP_INITIAL_STATE now
if(Phase() == PPP_ESTABLISHMENT_PHASE && Interface().Parent()) { if(Phase() == PPP_ESTABLISHMENT_PHASE) {
// the device is already up // the device is already up
NewPhase(PPP_DOWN_PHASE); NewPhase(PPP_DOWN_PHASE);
// this says the following DownEvent() was not caused by // this says the following DownEvent() was not caused by
@ -903,7 +916,12 @@ PPPStateMachine::RCAEvent(struct mbuf *packet)
PPPOptionHandler *handler; PPPOptionHandler *handler;
for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) { for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
handler = LCP().OptionHandlerAt(index); handler = LCP().OptionHandlerAt(index);
handler->ParseAck(&ack); if(handler->ParseAck(ack) != B_OK) {
m_freem(packet);
locker.UnlockNow();
CloseEvent();
return;
}
} }
switch(State()) { switch(State()) {
@ -974,10 +992,21 @@ PPPStateMachine::RCNEvent(struct mbuf *packet)
for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) { for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
handler = LCP().OptionHandlerAt(index); handler = LCP().OptionHandlerAt(index);
if(nak_reject.Code() == PPP_CONFIGURE_NAK) if(nak_reject.Code() == PPP_CONFIGURE_NAK) {
handler->ParseNak(&nak_reject); if(handler->ParseNak(nak_reject) != B_OK) {
else if(nak_reject.Code() == PPP_CONFIGURE_REJECT) m_freem(packet);
handler->ParseReject(&nak_reject); 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()) { switch(State()) {
@ -1030,7 +1059,7 @@ PPPStateMachine::RTREvent(struct mbuf *packet)
if(fID == mtod(packet, ppp_lcp_packet*)->id) if(fID == mtod(packet, ppp_lcp_packet*)->id)
fID -= 128; fID -= 128;
fAuthenticationStatus = PPP_NOT_AUTHENTICATED; fLocalAuthenticationStatus = PPP_NOT_AUTHENTICATED;
fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED; fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED;
switch(State()) { switch(State()) {
@ -1107,6 +1136,8 @@ PPPStateMachine::RTAEvent(struct mbuf *packet)
case PPP_OPENED_STATE: case PPP_OPENED_STATE:
NewState(PPP_REQ_SENT_STATE); NewState(PPP_REQ_SENT_STATE);
NewPhase(PPP_ESTABLISHMENT_PHASE);
// indicates to handlers that we are reconfiguring
locker.UnlockNow(); locker.UnlockNow();
ThisLayerDown(); ThisLayerDown();
SendConfigureRequest(); SendConfigureRequest();
@ -1185,12 +1216,14 @@ PPPStateMachine::RXJBadEvent(struct mbuf *packet)
ThisLayerFinished(); ThisLayerFinished();
break; break;
case PPP_STOPPING_STATE:
case PPP_REQ_SENT_STATE: case PPP_REQ_SENT_STATE:
case PPP_ACK_RCVD_STATE: case PPP_ACK_RCVD_STATE:
case PPP_ACK_SENT_STATE: case PPP_ACK_SENT_STATE:
NewState(PPP_STOPPED_STATE); NewState(PPP_STOPPED_STATE);
case PPP_STOPPING_STATE:
NewPhase(PPP_TERMINATION_PHASE);
case PPP_STOPPED_STATE: case PPP_STOPPED_STATE:
locker.UnlockNow(); locker.UnlockNow();
ThisLayerFinished(); ThisLayerFinished();
@ -1198,6 +1231,8 @@ PPPStateMachine::RXJBadEvent(struct mbuf *packet)
case PPP_OPENED_STATE: case PPP_OPENED_STATE:
NewState(PPP_STOPPING_STATE); NewState(PPP_STOPPING_STATE);
NewPhase(PPP_TERMINATION_PHASE);
// indicates to handlers that we are terminating
InitializeRestartCount(); InitializeRestartCount();
locker.UnlockNow(); locker.UnlockNow();
ThisLayerDown(); ThisLayerDown();
@ -1283,7 +1318,6 @@ PPPStateMachine::RCREvent(struct mbuf *packet)
{ {
PPPConfigurePacket request(packet), nak(PPP_CONFIGURE_NAK), PPPConfigurePacket request(packet), nak(PPP_CONFIGURE_NAK),
reject(PPP_CONFIGURE_REJECT); reject(PPP_CONFIGURE_REJECT);
PPPOptionHandler *handler;
// we should not use the same id as the peer // we should not use the same id as the peer
if(fID == mtod(packet, ppp_lcp_packet*)->id) if(fID == mtod(packet, ppp_lcp_packet*)->id)
@ -1293,34 +1327,46 @@ PPPStateMachine::RCREvent(struct mbuf *packet)
reject.SetID(request.ID()); reject.SetID(request.ID());
// each handler should add unacceptable values for each item // each handler should add unacceptable values for each item
bool handled; status_t result;
int32 error; // the return value of ParseRequest()
for(int32 item = 0; item <= request.CountItems(); item++) { PPPOptionHandler *handler;
// if we sent too many naks we should not append additional values for(int32 index = 0; index < request.CountItems(); index++) {
if(fNakCounter == 0 && item == request.CountItems()) handler = LCP().OptionHandlerFor(request.ItemAt(index)->type);
break;
handled = false; if(!handler || !handler->IsEnabled()) {
// unhandled items should be added to reject
for(int32 index = 0; index < LCP().CountOptionHandlers(); reject.AddItem(request.ItemAt(index));
index++) { continue;
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(!handled && item < request.CountItems()) { result = handler->ParseRequest(request, index, nak, reject);
// unhandled items should be added to reject
reject.AddItem(request.ItemAt(item)); 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++) { for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
// add all items // add all items
if(!LCP().OptionHandlerAt(index)->AddToRequest(&request)) { if(LCP().OptionHandlerAt(index)->AddToRequest(request) != B_OK) {
CloseEvent(); CloseEvent();
return false; return false;
} }
@ -1518,8 +1564,13 @@ PPPStateMachine::SendConfigureAck(struct mbuf *packet)
PPPConfigurePacket ack(packet); PPPConfigurePacket ack(packet);
// notify all option handlers that we are sending an ack for each value // notify all option handlers that we are sending an ack for each value
for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
LCP().OptionHandlerAt(index)->SendingAck(&ack); if(LCP().OptionHandlerAt(index)->SendingAck(ack) != B_OK) {
m_freem(packet);
CloseEvent();
return false;
}
}
return LCP().Send(packet) == B_OK; return LCP().Send(packet) == B_OK;
} }

View File

@ -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 <KPPPConfigurePacket.h>
#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;
}

View File

@ -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 <KPPPOptionHandler.h>
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