Moved OptionHandlers to LCP (where they actually belong).

Added some initial code to get general (as far as possible) multilink support (the modules must be aware of whether they belong to the device or to the bundle).
PPPDevice now reports speed and number of bytes in the output queue.
Removed PPP_CTOR_DTOR_PHASE. Modules can be loaded in PPP_DOWN_PHASE.
Worked on events and actions.
Some minor changes/fixes.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4008 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald 2003-07-17 16:46:08 +00:00
parent b912b1e24f
commit 7aa79f33d8
11 changed files with 1492 additions and 92 deletions

View File

@ -13,6 +13,7 @@
#define PPP_DEVICE_KEY "Device"
#define PPP_AUTHENTICATOR_KEY "Authenticator"
#define PPP_PEER_AUTHENTICATOR_KEY "Peer-Authenticator"
#define PPP_MULTILINK_KEY "Multilink-Protocol"
// settings values
#define PPP_CLIENT_MODE_VALUE "Client"
@ -27,21 +28,26 @@
#define PPP_ERROR_BASE B_ERRORS_END
// return values for Receive methods in addition to B_ERROR and B_OK
// return values for Send()/Receive() methods in addition to B_ERROR and B_OK
// PPP_UNHANDLED is also used by PPPOptionHandler
enum {
// B_ERROR means that the packet is corrupted
// B_OK means the packet was handled correctly
// return values for PPPProtocol and PPPEncapsulator
// return values for PPPProtocol and PPPEncapsulator (and PPPOptionHandler)
PPP_UNHANDLED = PPP_ERROR_BASE,
// The packet does not belong to this handler.
// Do not delete the packet when you return this!
// For PPPOptionHandler: the item is unrecognized
// return values of PPPInterface::Receive()
PPP_DISCARDED,
// packet was silently discarded
PPP_REJECTED,
// a protocol-reject
PPP_NO_CONNECTION
// could not send a packet because device is not connected
};
// module key types (used when loading a module)
@ -50,14 +56,15 @@ enum {
PPP_DEVICE_TYPE,
PPP_PROTOCOL_TYPE,
PPP_AUTHENTICATOR_TYPE,
PPP_PEER_AUTHENTICATOR_TYPE
PPP_PEER_AUTHENTICATOR_TYPE,
PPP_MULTILINK_TYPE
};
// protocol and encapsulator flags
enum {
PPP_NO_FLAGS = 0x00,
PPP_ALWAYS_ALLOWED = 0x01,
// protocol may send/receive while we are authenticating
// protocol may send/receive in PPP_ESTABLISHMENT_PHASE
PPP_NEEDS_DOWN = 0x02
// protocol needs a Down() in addition to a Reset() to
// terminate the connection properly (losing the connection
@ -75,8 +82,6 @@ enum PPP_PHASE {
// the normal protocols like IP (i.e., IPCP)
// the following must not be used by protocols!
PPP_CTOR_DTOR_PHASE = -1,
// set on construction/destruction of the interface
PPP_DOWN_PHASE = 0,
PPP_TERMINATION_PHASE = 1,
// this is the selected phase when we are GOING down

View File

@ -34,11 +34,32 @@ class PPPDevice {
bool IsUp() const
{ return fIsUp; }
// The biggest of the two tranfer rates will be set in ifnet.
// These methods should return default values when disconnected.
virtual uint32 InputTransferRate() const = 0;
virtual uint32 OutputTransferRate() const = 0;
virtual uint32 CountOutputBytes() const = 0;
// how many bytes are waiting to be sent?
virtual status_t Send(mbuf *packet) = 0;
// this should enqueue the packet and return immediately
status_t PassToInterface(mbuf *packet);
// This will pass the packet to the interface's queue.
// Do not call Interface::ReceiveFromDevice directly
// if this can block a Send()!
protected:
void SetUp(bool isUp);
// report up/down events
// Report that we are going up/down
// (from now on, the Up() process can be aborted).
// Abort if false is returned!
bool UpStarted();
bool DownStarted();
// report up/down events
void UpEvent();
void UpFailedEvent();
void DownEvent();
protected:
bool fIsUp;

View File

@ -0,0 +1,127 @@
#ifndef _K_PPP_FINITE_STATE_MACHINE__H
#define _K_PPP_FINITE_STATE_MACHINE__H
#include "KPPPLCP.h"
#include "Locker.h"
class PPPFiniteStateMachine {
friend class PPPInterface;
friend class PPPLCP;
private:
// may only be constructed/destructed by PPPInterface
PPPFiniteStateMachine(PPPInterface& interface);
~PPPFiniteStateMachine();
// copies are not allowed!
PPPFiniteStateMachine(const PPPFiniteStateMachine& copy);
PPPFiniteStateMachine& operator= (const PPPFiniteStateMachine& copy);
public:
PPPInterface *Interface() const
{ return fInterface; }
PPPLCP& LCP() const
{ return Interface()->LCP(); }
PPP_STATE State() const
{ return fState; }
PPP_PHASE Phase() const
{ return fPhase; }
uint8 NextID();
// return the next id for lcp_packets
// public events
void AuthenticationRequested();
void AuthenticationAccepted(const char *name);
void AuthenticationDenied(const char *name);
const char *AuthenticationName() const;
// returns NULL if not authenticated
PPP_AUTHENTICATION_STATUS AuthenticationStatus() const
{ return fAuthenticationStatus; }
void PeerAuthenticationRequested();
void PeerAuthenticationAccepted(const char *name);
void PeerAuthenticationDenied(const char *name);
const char *PeerAuthenticationName() const;
// returns NULL if not authenticated
PPP_AUTHENTICATION_STATUS PeerAuthenticationStatus() const
{ return fPeerAuthenticationStatus; }
bool TLSNotify();
bool TLFNotify();
void UpFailedEvent();
void UpEvent();
void DownEvent();
private:
BLocker& Locker()
{ return fLock; }
void LeaveConstructionPhase();
void EnterDestructionPhase();
// private FiniteStateMachine methods
void NewState(PPP_STATE next);
// private events
void OpenEvent();
void CloseEvent();
void TOGoodEvent();
void TOBadEvent();
void RCRGoodEvent(mbuf *packet);
void RCRBadEvent(mbuf *nak, mbuf *reject);
void RCAEvent(mbuf *packet);
void RCNEvent(mbuf *packet);
void RTREvent(mbuf *packet);
void RTAEvent(mbuf *packet);
void RUCEvent(mbuf *packet, uint16 protocol);
void RXJGoodEvent(mbuf *packet);
void RXJBadEvent(mbuf *packet);
void RXREvent(mbuf *packet);
// general events (for Good/Bad events)
void TimerEvent();
void RCREvent(mbuf *packet);
void RXJEvent(mbuf *packet);
// actions
void IllegalEvent(PPP_EVENT event);
void ThisLayerUp();
void ThisLayerDown();
void ThisLayerStarted();
void ThisLayerFinished();
void InitializeRestartCount();
void ZeroRestartCount();
void SendConfigureRequest();
void SendConfigureAck(mbuf *packet);
void SendConfigureNak(mbuf *packet);
void SendTerminateRequest();
void SendTerminateAck(mbuf *request);
void SendCodeReject(mbuf *packet, uint16 protocol);
void SendEchoReply(mbuf *request);
private:
PPPInterface *fInterface;
PPP_PHASE fPhase;
PPP_STATE fState;
vint32 fID;
PPP_AUTHENTICATION_STATUS fAuthenticationStatus,
fPeerAuthenticationStatus;
int32 fAuthenticatorIndex, fPeerAuthenticatorIndex;
BLocker fLock;
// counters and timers
int32 fMaxRequest, fMaxTerminate, fMaxNak;
int32 fRequestCounter, fTerminateCounter, fNakCounter;
bigtime_t fTimeout;
// last time we sent a packet
};
#endif

View File

@ -5,7 +5,7 @@
#include "KPPPDefs.h"
#include "KPPPFSM.h"
#include "KPPPFiniteStateMachine.h"
#include "KPPPLCP.h"
#include "List.h"
@ -24,7 +24,7 @@ class PPPInterface {
PPPInterface& operator= (const PPPInterface& copy);
public:
PPPInterface(driver_settings *settings);
PPPInterface(driver_settings *settings, PPPInterface *parent = NULL);
~PPPInterface();
status_t InitCheck() const;
@ -32,8 +32,10 @@ class PPPInterface {
driver_settings* Settings()
{ return fSettings; }
PPPFSM& FSM() const
{ return fFSM; }
PPPFiniteStateMachine& FiniteStateMachine() const
{ return fFiniteStateMachine; }
PPPLCP& LCP() const
{ return fLCP; }
bool RegisterInterface();
// adds us to the manager module and
@ -69,11 +71,15 @@ class PPPInterface {
PPPEncapsulator *EncapsulatorFor(uint16 protocol,
PPPEncapsulator start = NULL) const;
bool AddOptionHandler(PPPOptionHandler *handler);
bool RemoveOptionHandler(PPPOptionHandler *handler);
int32 CountOptionHandlers() const
{ return fOptionHandlers.CountItems(); }
PPPOptionHandler *OptionHandlerAt(int32 index) const;
// multilink methods
void AddChild(PPPInterface *child);
void RemoveChild(PPPInterface *child);
int32 CountChildren() const
{ return fChildren.CountItems(); }
PPPInterface *Parent() const
{ return fParent; }
bool IsMultilink() const
{ return fIsMultilink; }
void SetAutoRedial(bool autoredial = true);
bool DoesAutoRedial() const
@ -87,9 +93,9 @@ class PPPInterface {
{ return fMode; }
// client or server mode?
PPP_STATE State() const
{ return FSM().State(); }
{ return FiniteStateMachine().State(); }
PPP_PHASE Phase() const
{ return FSM().Phase(); }
{ return FiniteStateMachine().Phase(); }
bool Up();
// in server mode Up() listens for an incoming connection
@ -97,7 +103,7 @@ class PPPInterface {
bool IsUp() const;
/* void EnableReports(PPP_REPORT type, thread_id thread,
PPP_REPORT_FLAGS flags);
int32 flags);
void DisableReports(PPP_REPORT type, thread_id thread);
bool DoesReport(PPP_REPORT type, thread_id thread); */
@ -110,22 +116,31 @@ class PPPInterface {
status_t SendToDevice(mbuf *packet, uint16 protocol);
status_t ReceiveFromDevice(mbuf *packet);
// This is called by the receive-thread.
// Only call this if it does not block Send() or
// SendToDevice()!
private:
PPPLCP& LCP() const
{ return fLCP; }
void CalculateMRU();
// multilink methods
void SetParent(PPPInterface *parent)
{ fParent = parent; }
// void Report(PPP_REPORT type, int32 code, void *data, int32 length);
private:
driver_parameter *fSettings;
PPPFSM fFSM;
PPPFiniteStateMachine fFiniteStateMachine;
PPPLCP fLCP;
ifnet *fIfnet;
uint32 fLinkMTU, fMRU, fHeaderLength;
PPPInterface *fParent;
List<PPPInterface*> fChildren;
bool fIsMultilink;
bool fAutoRedial, fDialOnDemand;
vint32 fAccesing;
@ -134,9 +149,7 @@ class PPPInterface {
PPPDevice *fDevice;
PPPEncapsulator *fFirstEncapsulator;
List<PPPProtocol*> fProtocols;
List<PPPOptionHandler*> fOptionHandlers;
List<ppp_module_info*> fModules;
BLocker& fGeneralLock;

View File

@ -25,10 +25,24 @@ class PPPLCP : public PPPProtocol {
PPPLCP& operator= (const PPPLCP& copy);
public:
PPPFiniteStateMachine& FiniteStateMachine() const
{ return Interface()->FiniteStateMachine(); }
bool AddOptionHandler(PPPOptionHandler *handler);
bool RemoveOptionHandler(PPPOptionHandler *handler);
int32 CountOptionHandlers() const
{ return fOptionHandlers.CountItems(); }
PPPOptionHandler *OptionHandlerAt(int32 index) const;
void SetTarget(PPPEncapsulator *target)
{ fTarget = target; }
// if target != all packtes will be passed to the encapsulator
// instead of the interface/device
private:
List<PPPOptionHandler*> fOptionHandlers;
PPPEncapsulator *fTarget;
};

View File

@ -9,8 +9,11 @@ class PPPInterface;
typedef struct ppp_module_info {
module_info minfo;
status_t (*control)(uint32 op, void *data, size_t length);
status_t (*add_to)(PPPInterface *interface,
status_t (*add_to)(PPPInterface *mainInterface, PPPInterface *subInterface,
driver_parameter *settings, int32 type);
// multilink: handlers that must run on a real device
// should be added to subInterface while mainInterface
// handlers are used for the bundle of interfaces
} ppp_module_info;

View File

@ -29,7 +29,7 @@ class PPPOptionHandler {
// e.g.: remove list of rejected values
// we want to send a configure request or we received a reply
virtual bool AddToRequest(PPPConfigurePacket *request) = 0;
virtual status_t AddToRequest(PPPConfigurePacket *request) = 0;
virtual void ParseNak(const PPPConfigurePacket *nak) = 0;
// create next request based on these and previous values
virtual void ParseReject(const PPPConfigurePacket *reject) = 0;
@ -38,10 +38,12 @@ class PPPOptionHandler {
// this is called for all handlers
// peer sent configure request
virtual bool ParseConfigureRequest(const PPPConfigurePacket *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;
// notification that we ack these values
private:
const char *fName;

File diff suppressed because it is too large Load Diff

View File

@ -23,12 +23,21 @@
// - maybe some protocols must go down instead of being reset -> add flag for this
PPPInterface::PPPInterface(driver_settings *settings)
PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NULL)
: fSettings(dup_driver_settings(settings)),
FSM(*this), LCP(*this), fIfnet(NULL), fLinkMTU(0),
fAccessing(0), fDevice(NULL), fFirstEncapsulator(NULL),
fGeneralLock(FSM().Locker())
FiniteStateMachine(*this), LCP(*this), fIfnet(NULL), fLinkMTU(1500),
fAccessing(0), fChildrenCount(0), fDevice(NULL), fFirstEncapsulator(NULL),
fGeneralLock(FiniteStateMachine().Locker())
{
// are we a multilink subinterface?
if(parent && parent->IsMultilink()) {
fParent = parent;
fIsMultilink = true;
} else {
fParent = NULL;
fIsMultilink = false;
}
if(!fSettings)
return;
@ -58,8 +67,6 @@ PPPInterface::PPPInterface(driver_settings *settings)
// load all protocols and the device
LoadModules(fSettings, 0, fSettings->parameter_count);
FSM().LeaveConstructionPhase();
}
@ -69,9 +76,6 @@ PPPInterface::~PPPInterface()
// remove our iface, so that nobody will access it:
// go down if up
// unregister from ppp_manager
FSM().EnterDestructionPhase();
// destroy and remove:
// device
// protocols
@ -85,8 +89,14 @@ PPPInterface::~PPPInterface()
status_t
PPPInterface::InitCheck() const
{
if(!fDevice
|| !fSettings)
if(!fSettings)
return B_ERROR;
// sub-interfaces should have a device
if(IsMultilink()) {
if(Parent() && !fDevice)
return B_ERROR;
} else if(!fDevice)
return B_ERROR;
return B_OK;
@ -104,6 +114,10 @@ PPPInterface::RegisterInterface()
return false;
// we cannot register if something is wrong
// only MainInterfaces get an ifnet
if(IsMultilink() && Parent() && Parent()->RegisterInterface())
return true;
ppp_manager_info *manager;
if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &manager) != B_OK)
return false;
@ -127,6 +141,10 @@ PPPInterface::UnregisterInterface()
return true;
// we are already unregistered
// only MainInterfaces get an ifnet
if(IsMultilink() && Parent())
return true;
ppp_manager_info *manager;
if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &manager) != B_OK)
return false;
@ -143,8 +161,11 @@ PPPInterface::UnregisterInterface()
void
PPPInterface::SetLinkMTU(uint32 linkMTU)
{
if(linkMTU < fLinkMTU && linkMTU > 234)
fLinkMTU = linkMTU;
LockerHelper locker(fLock);
fLinkMTU = linkMTU;
CalculateMRU();
}
@ -174,7 +195,13 @@ PPPInterface::SetDevice(PPPDevice *device)
if(!device)
return false;
if(Phase() != PPP_CTOR_DTOR_PHASE)
if(IsMultilink() && !Parent())
return false;
// main interfaces do not have devices
LockerHelper locker(fLock);
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
@ -195,7 +222,9 @@ PPPInterface::AddProtocol(PPPProtocol *protocol)
if(!protocol)
return false;
if(Phase() != PPP_CTOR_DTOR_PHASE)
LockerHelper locker(fLock);
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
@ -209,7 +238,9 @@ PPPInterface::AddProtocol(PPPProtocol *protocol)
bool
PPPInterface::RemoveProtocol(PPPProtocol *protocol)
{
if(Phase() != PPP_CTOR_DTOR_PHASE)
LockerHelper locker(fLock);
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
@ -258,7 +289,9 @@ PPPInterface::AddEncapsulator(PPPEncapsulator *encapsulator)
if(!encapsulator)
return false;
if(Phase() != PPP_CTOR_DTOR_PHASE)
LockerHelper locker(fLock);
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
@ -300,7 +333,9 @@ PPPInterface::AddEncapsulator(PPPEncapsulator *encapsulator)
bool
PPPInterface::RemoveEncapsulator(PPPEncapsulator *encapsulator)
{
if(Phase() != PPP_CTOR_DTOR_PHASE)
LockerHelper locker(fLock);
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
@ -346,39 +381,34 @@ PPPInterface::EncapsulatorFor(uint16 protocol,
bool
PPPInterface::AddOptionHandler(PPPOptionHandler *handler)
PPPInterface::AddChild(PPPInterface *child)
{
if(!handler)
return false
LockerHelper locker(fLock);
if(Phase() != PPP_CTOR_DTOR_PHASE)
if(fChildren.HasItem(child) || !fChildren.AddItem(child))
return false;
// a running connection may not change
fOptionHandlers.AddItem(handler);
child->SetParent(this);
CalculateMRU();
return true;
}
bool
PPPInterface::RemoveOptionHandler(PPPOptionHandler *handler)
PPPInterface::RemoveChild(PPPInterface *child)
{
if(Phase() != PPP_CTOR_DTOR_PHASE)
LockerHelper locker(fLock);
if(!fChildren.RemoveItem(child))
return false;
// a running connection may not change
return fOptionHandlers.RemoveItem(handler);
}
PPPOptionHandler*
PPPInterface::OptionHandlerAt(int32 index) const
{
PPPOptionHandler *handler = fOptionHandlers.ItemAt(index);
child->SetParent(NULL);
if(handler == fOptionHandlers.DefaultItem())
return NULL;
CalculateMRU();
return handler;
return true;
}
@ -419,7 +449,7 @@ PPPInterface::Up()
// instead of waiting for state change we should wait until
// all retries are done
if(!InitCheck() || Phase() != PPP_CTOR_DTOR_PHASE)
if(!InitCheck() || Phase() != PPP_DOWN_PHASE)
return false;
if(IsUp())
@ -441,7 +471,7 @@ PPPInterface::Down()
// instead of waiting for state change we should wait until
// all retries are done
if(!InitCheck() || Phase() != PPP_CTOR_DTOR_PHASE)
if(!InitCheck())
return false;
// TODO:
@ -455,6 +485,10 @@ bool
PPPInterface::IsUp() const
{
LockerHelper locker(fGeneralLock);
// set running flag if successful
if(Ifnet())
return Ifnet()->if_flags & IFF_RUNNING;
@ -489,20 +523,44 @@ bool
PPPInterface::LoadModules(const driver_settings *settings,
int32 start, int32 count)
{
if(Phase() != PPP_CTOR_DTOR_PHASE)
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
int32 type;
// which type key was used for loading this module?
const char *name = NULL;
// multilink handling
for(int32 i = start;
i < settings->parameter_count && i < start + count;
i++) {
if(!strcasecmp(settings->parameters[i].name, PPP_MULTILINK_KEY)
&& settings->parameters[i].value_count > 0) {
if(!LoadModule(settings->parameters[i].value[0],
parameters[i].parameters, PPP_MULTILINK_TYPE))
return false;
break;
}
}
// are we a multilink main interface?
if(IsMultilink() && !Parent()) {
// main interfaces only load the multilink module
// and create a child using their settings
AddChild(new PPPInterface(settings, this));
return true;
}
for(int32 i = start;
i < settings->parameter_count && i < start + count;
i++) {
type = -1;
const char *name = settings->parameters[i].name;
name = settings->parameters[i].name;
if(!strcasecmp(name, PPP_LOAD_MODULE_KEY))
type = PPP_LOAD_MODULE_TYPE;
@ -531,7 +589,7 @@ bool
PPPInterface::LoadModule(const char *name, const driver_parameter *parameter,
int32 type)
{
if(Phase() != PPP_CTOR_DTOR_PHASE)
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
@ -546,7 +604,7 @@ PPPInterface::LoadModule(const char *name, const driver_parameter *parameter,
if(get_module(module_name, (module_info**) &module) != B_OK)
return false;
if(!module->add_to(this, parameter, type))
if(!module->add_to(Parent()?Parent():this, this, parameter, type))
return false;
// add the module to the list of loaded modules
@ -619,16 +677,22 @@ PPPInterface::Receive(mbuf *packet, uint16 protocol)
// the handler might be upped by this packet.
PPPEncapsulator *encapsulator_handler = EncapsulatorFor(protocol);
for(; encapsulator_handler;
encapsulator_handler = EncapsulatorFor(protocol, encapsulator_handler)) {
encapsulator_handler = EncapsulatorFor(protocol, encapsulator_handler->Next())) {
if(!encapsulator_handler->IsEnabled()) {
// disabled handlers should not be used
result = PPP_REJECTED;
if(!encapsulator_handler->Next())
break;
continue;
// disabled handlers should not be used
}
result = encapsulator_handler->Receive(packet, protocol);
if(result == PPP_UNHANDLED)
if(result == PPP_UNHANDLED) {
if(!encapsulator_handler->Next())
break;
continue;
}
return result;
}
@ -653,14 +717,15 @@ PPPInterface::Receive(mbuf *packet, uint16 protocol)
return result;
}
// packet is unhandled
m_free(packet);
// maybe the parent interface can handle it
if(Parent())
return Parent->Receive(packet, protocol);
if(result == PPP_UNHANDLED)
m_free(packet);
return PPP_DISCARDED;
else {
// TODO:
// send protocol-reject!
FiniteStateMachine()->RUCEvent(packet, protocol);
return PPP_REJECTED;
}
}
@ -675,7 +740,7 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
return B_ERROR;
// we must pass the basic tests like:
// do we have a device?
// do we have a device (as main interface)?
// did we load all modules?
if(InitCheck() != B_OK) {
m_free(packet);
@ -689,8 +754,10 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
}
// go up if DialOnDemand enabled and we are down
if(DoesDialOnDemand() && Phase() == PPP_DOWN_PHASE)
if(DoesDialOnDemand() && (Phase() == PPP_DOWN_PHASE
|| Phase() == PPP_ESTABLISHMENT_PHASE))
Up();
// Up() waits until it is done
// check if protocol is allowed and everything is up
PPPProtocol *sending_protocol = ProtocolFor(protocol);
@ -712,20 +779,26 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
if(packet == NULL)
return B_ERROR;
// check if packet is too big
if((packet->m_flags & M_PKTHDR && packet->m_pkt_hdr.len > LinkMTU())
|| packet->m_len > LinkMTU()) {
m_free(packet);
return B_ERROR;
}
// set protocol (the only header field)
protocol = htons(protocol);
uint16 *header = mtod(packet, uint16*);
*header = protocol;
// pass to device
return Device()->Send(packet);
// pass to device/children
if(!IsMultilink() || Parent()) {
// check if packet is too big for device
if((packet->m_flags & M_PKTHDR && packet->m_pkt_hdr.len > LinkMTU())
|| packet->m_len > LinkMTU()) {
m_free(packet);
return B_ERROR;
}
return Device()->Send(packet);
} else {
// the multilink encapsulator should have sent it to some child interface
m_free(packet);
return B_ERROR;
}
}
@ -755,7 +828,7 @@ PPPInterface::ReceiveFromDevice(mbuf *packet)
if(!packet->m_pkthdr.rcvif) {
m_free(packet);
return false;
return B_ERROR;
}
}
@ -779,6 +852,13 @@ PPPInterface::CalculateMRU()
fMRU -= fHeaderLength;
if(Parent())
Parent()->CalculateMRU();
for(int32 i = 0; i < fChildren.CountItems(); i++)
fMRU += fChildren.ItemAt(i)->MRU();
// add our subinterfaces' MRU (so we have the MRRU)
if(Ifnet()) {
Ifnet()->if_mtu = fMRU;
Ifnet()->if_hdrlen = fHeaderLength;

View File

@ -1,2 +1,62 @@
#include "KPPPLCP.h"
// TODO:
// - add support for multilink interfaces
// (LCP packets may be received over MP encapsulators
// so we should return the reply using the same encapsulator)
// - add LCP extension handlers
PPPLCP::PPPLCP(PPPInterface& interface)
: PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL
, AF_UNSPEC, &interface, NULL, PPP_ALWAYS_ALLOWED),
fTarget(NULL)
{
}
PPPLCP::~PPPLCP()
{
}
bool
PPPLCP::AddOptionHandler(PPPOptionHandler *handler)
{
if(!handler)
return false
LockerHelper locker(FiniteStateMachine().Locker());
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
fOptionHandlers.AddItem(handler);
}
bool
PPPLCP::RemoveOptionHandler(PPPOptionHandler *handler)
{
LockerHelper locker(FiniteStateMachine().Locker());
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
return fOptionHandlers.RemoveItem(handler);
}
PPPOptionHandler*
PPPLCP::OptionHandlerAt(int32 index) const
{
PPPOptionHandler *handler = fOptionHandlers.ItemAt(index);
if(handler == fOptionHandlers.DefaultItem())
return NULL;
return handler;
}

View File

@ -1,6 +1,8 @@
#ifndef _SETTINGS_TOOLS__H
#define _SETTINGS_TOOLS__H
// remove this as soon as we get the extended driver_settings API
struct driver_settings;
struct driver_parameter;
@ -19,6 +21,8 @@ void add_parameter(const driver_parameter *from, driver_parameter *to)
bool get_boolean_value(const char *string, bool unknownValue);
const char *get_settings_value(const char *name, const driver_settings *settings);
const char *get_parameter_value(const char *name, const driver_parameter *parameters)
{ get_settings_value(name, (driver_settings*) &parameter->parameter_count); }
#endif