Added MRU option handler.
Fixed wrong definition of MRU. Added the StackControl() method to all handlers (expect PPPDevice) and changed how the netstack ioctls are passed to the handlers. Added a template for iterating over indexed lists (needed methods: CountItems() and ItemAt()). This simplified StackControlEachHandler() a little bit. Some minor changes. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4673 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -33,10 +33,8 @@ class PPPDevice {
|
||||
|
||||
virtual status_t Control(uint32 op, void *data, size_t length);
|
||||
|
||||
virtual bool SetMTU(uint32 MTU);
|
||||
uint32 MTU() const
|
||||
{ return fMTU; }
|
||||
virtual uint32 PreferredMTU() const = 0;
|
||||
|
||||
// these calls must not block
|
||||
virtual void Up() = 0;
|
||||
@@ -64,6 +62,9 @@ class PPPDevice {
|
||||
virtual void Pulse();
|
||||
|
||||
protected:
|
||||
void SetMTU(uint32 MTU)
|
||||
{ fMTU = MTU; }
|
||||
|
||||
// Report that we are going up/down
|
||||
// (from now on, the Up() process can be aborted).
|
||||
// Abort if false is returned!
|
||||
@@ -77,6 +78,7 @@ class PPPDevice {
|
||||
|
||||
protected:
|
||||
uint32 fMTU;
|
||||
// always hold this value up-to-date!
|
||||
bool fIsUp;
|
||||
|
||||
status_t fInitStatus;
|
||||
|
||||
@@ -58,6 +58,8 @@ class PPPEncapsulator {
|
||||
{ return fUpRequested; }
|
||||
|
||||
virtual status_t Control(uint32 op, void *data, size_t length);
|
||||
virtual status_t StackControl(uint32 op, void *data);
|
||||
// called by netstack (forwarded by PPPInterface)
|
||||
|
||||
void SetNext(PPPEncapsulator *next)
|
||||
{ fNext = next; }
|
||||
|
||||
@@ -36,17 +36,19 @@ struct ppp_module_info;
|
||||
|
||||
class PPPInterface {
|
||||
friend class PPPStateMachine;
|
||||
friend class PPPManager;
|
||||
|
||||
private:
|
||||
// copies are not allowed!
|
||||
PPPInterface(const PPPInterface& copy);
|
||||
PPPInterface& operator= (const PPPInterface& copy);
|
||||
|
||||
public:
|
||||
|
||||
// only PPPManager may construct us!
|
||||
PPPInterface(interface_id ID, driver_settings *settings,
|
||||
PPPInterface *parent = NULL);
|
||||
~PPPInterface();
|
||||
|
||||
|
||||
public:
|
||||
void Delete();
|
||||
|
||||
status_t InitCheck() const;
|
||||
@@ -80,12 +82,12 @@ class PPPInterface {
|
||||
uint32 DisconnectAfterIdleSince() const
|
||||
{ return fDisconnectAfterIdleSince; }
|
||||
|
||||
void SetMRU(uint32 MRU);
|
||||
bool SetMRU(uint32 MRU);
|
||||
uint32 MRU() const
|
||||
{ return fMRU; }
|
||||
// this is the smallest MRU that we and the peer have
|
||||
void SetInterfaceMTU(uint32 interfaceMTU)
|
||||
{ SetMRU(interfaceMTU - fHeaderLength); }
|
||||
bool SetInterfaceMTU(uint32 interfaceMTU)
|
||||
{ return SetMRU(interfaceMTU - fHeaderLength); }
|
||||
uint32 InterfaceMTU() const
|
||||
{ return fInterfaceMTU; }
|
||||
// this is the MRU including encapsulator overhead
|
||||
@@ -125,11 +127,11 @@ class PPPInterface {
|
||||
bool IsMultilink() const
|
||||
{ return fIsMultilink; }
|
||||
|
||||
void SetAutoRedial(bool autoredial = true);
|
||||
void SetAutoRedial(bool autoRedial = true);
|
||||
bool DoesAutoRedial() const
|
||||
{ return fAutoRedial; }
|
||||
|
||||
void SetDialOnDemand(bool dialondemand = true);
|
||||
void SetDialOnDemand(bool dialOnDemand = true);
|
||||
bool DoesDialOnDemand() const
|
||||
{ return fDialOnDemand; }
|
||||
|
||||
@@ -192,14 +194,12 @@ class PPPInterface {
|
||||
|
||||
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
|
||||
status_t StackControlEachHandler(uint32 op, void *data);
|
||||
// this calls StackControl() with the given parameters for each handler
|
||||
|
||||
void CalculateInterfaceMTU();
|
||||
void CalculateBaudRate();
|
||||
|
||||
bool SetupDialOnDemand();
|
||||
|
||||
void Redial(uint32 delay);
|
||||
|
||||
// multilink methods
|
||||
|
||||
@@ -40,6 +40,8 @@ class PPPLCPExtension {
|
||||
{ return fCode; }
|
||||
|
||||
virtual status_t Control(uint32 op, void *data, size_t length);
|
||||
virtual status_t StackControl(uint32 op, void *data);
|
||||
// called by netstack (forwarded by PPPInterface)
|
||||
|
||||
virtual status_t Receive(struct mbuf *packet, uint8 code) = 0;
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ class PPPOptionHandler {
|
||||
{ return fEnabled; }
|
||||
|
||||
virtual status_t Control(uint32 op, void *data, size_t length);
|
||||
virtual status_t StackControl(uint32 op, void *data);
|
||||
// called by netstack (forwarded by PPPInterface)
|
||||
|
||||
// we want to send a configure request or we received a reply
|
||||
virtual status_t AddToRequest(PPPConfigurePacket& request) = 0;
|
||||
|
||||
@@ -55,15 +55,12 @@ class PPPProtocol {
|
||||
{ return fUpRequested; }
|
||||
|
||||
virtual status_t Control(uint32 op, void *data, size_t length);
|
||||
|
||||
virtual status_t SetupDialOnDemand();
|
||||
// This is not called when the protocol is added to the interface,
|
||||
// but only when someone enables DialOnDemand and interface is down.
|
||||
// Of course, your constructor may/should use this method (if needed).
|
||||
virtual status_t StackControl(uint32 op, void *data);
|
||||
// called by netstack (forwarded by PPPInterface)
|
||||
|
||||
virtual bool Up() = 0;
|
||||
virtual bool Down() = 0;
|
||||
// if DialOnDemand is implemented check for DialOnDemand settings change
|
||||
// if DialOnDemand is supported check for DialOnDemand settings change
|
||||
bool IsUp() const
|
||||
{ return fConnectionStatus == PPP_ESTABLISHED_PHASE; }
|
||||
bool IsDown() const
|
||||
|
||||
@@ -31,6 +31,16 @@ is_handler_allowed(T& handler, ppp_state state, ppp_phase phase)
|
||||
return false;
|
||||
}
|
||||
|
||||
// the list template does not support iterating over each item :(
|
||||
// this template iterates over each item in an indexed list
|
||||
template<class _LIST, class _FUNCTION>
|
||||
inline
|
||||
void
|
||||
ForEachItem(_LIST& list, _FUNCTION function)
|
||||
{
|
||||
for(int index = 0; index < list.CountItems(); index++)
|
||||
function(list.ItemAt(index));
|
||||
}
|
||||
|
||||
// These are very simple send/receive_data functions with a timeout
|
||||
// and there is a race condition beween has_data() and send/receive_data().
|
||||
|
||||
@@ -59,10 +59,6 @@ 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
|
||||
@@ -119,7 +115,7 @@ typedef struct ppp_device_info {
|
||||
|
||||
const driver_parameter *settings;
|
||||
|
||||
uint32 MTU, preferredMTU;
|
||||
uint32 MTU;
|
||||
uint32 inputTransferRate, outputTransferRate, outputBytesCount;
|
||||
} ppp_device_info;
|
||||
typedef struct ppp_device_info_t {
|
||||
|
||||
@@ -50,7 +50,6 @@ enum {
|
||||
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,
|
||||
|
||||
@@ -25,6 +25,6 @@ R5KernelStaticLibrary kernelppp :
|
||||
cpp.cpp
|
||||
|
||||
# integrated modules
|
||||
_KPPPMRUHandler.cpp
|
||||
_KPPPPFCHandler.cpp
|
||||
;
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ PPPDevice::Control(uint32 op, void *data, size_t length)
|
||||
strcpy(info->name, Name());
|
||||
info->settings = Settings();
|
||||
info->MTU = MTU();
|
||||
info->preferredMTU = PreferredMTU();
|
||||
info->inputTransferRate = InputTransferRate();
|
||||
info->outputTransferRate = OutputTransferRate();
|
||||
info->outputBytesCount = CountOutputBytes();
|
||||
|
||||
@@ -102,6 +102,18 @@ PPPEncapsulator::Control(uint32 op, void *data, size_t length)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPEncapsulator::StackControl(uint32 op, void *data)
|
||||
{
|
||||
switch(op) {
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPEncapsulator::SendToNext(struct mbuf *packet, uint16 protocol) const
|
||||
{
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "settings_tools.h"
|
||||
|
||||
// internal modules
|
||||
#include "_KPPPMRUHandler.h"
|
||||
#include "_KPPPPFCHandler.h"
|
||||
|
||||
|
||||
@@ -68,7 +69,7 @@ PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
|
||||
fDialRetriesLimit(0),
|
||||
fIdleSince(0),
|
||||
fMRU(1500),
|
||||
fInterfaceMTU(1498),
|
||||
fInterfaceMTU(1500),
|
||||
fHeaderLength(2),
|
||||
fAutoRedial(false),
|
||||
fDialOnDemand(false),
|
||||
@@ -81,6 +82,12 @@ PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
|
||||
fDeleteCounter(0)
|
||||
{
|
||||
// add internal modules
|
||||
// MRU
|
||||
_PPPMRUHandler *mruHandler =
|
||||
new _PPPMRUHandler(*this);
|
||||
if(mruHandler->InitCheck() != B_OK)
|
||||
delete mruHandler;
|
||||
// PFC
|
||||
_PPPPFCHandler *pfcHandler =
|
||||
new _PPPPFCHandler(fLocalPFCState, fPeerPFCState, *this);
|
||||
if(pfcHandler->InitCheck() != B_OK)
|
||||
@@ -255,14 +262,19 @@ PPPInterface::InitCheck() const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
PPPInterface::SetMRU(uint32 MRU)
|
||||
{
|
||||
if(MRU > Device()->MTU() - 2)
|
||||
return false;
|
||||
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
fMRU = MRU;
|
||||
|
||||
CalculateInterfaceMTU();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -420,17 +432,6 @@ 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 B_BAD_VALUE;
|
||||
}
|
||||
@@ -460,7 +461,7 @@ PPPInterface::SetDevice(PPPDevice *device)
|
||||
|
||||
fDevice = device;
|
||||
|
||||
fMRU = fDevice->MTU();
|
||||
fMRU = fDevice->MTU() - 2;
|
||||
|
||||
CalculateInterfaceMTU();
|
||||
CalculateBaudRate();
|
||||
@@ -727,47 +728,54 @@ PPPInterface::ChildAt(int32 index) const
|
||||
|
||||
|
||||
void
|
||||
PPPInterface::SetAutoRedial(bool autoredial = true)
|
||||
PPPInterface::SetAutoRedial(bool autoRedial = true)
|
||||
{
|
||||
if(Mode() == PPP_CLIENT_MODE)
|
||||
return;
|
||||
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
fAutoRedial = autoredial;
|
||||
fAutoRedial = autoRedial;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PPPInterface::SetDialOnDemand(bool dialondemand = true)
|
||||
PPPInterface::SetDialOnDemand(bool dialOnDemand = true)
|
||||
{
|
||||
// All protocols must check if DialOnDemand was enabled/disabled after this
|
||||
// interface went down. This is the only situation where a change is relevant.
|
||||
|
||||
// only clients support DialOnDemand
|
||||
if(Mode() != PPP_CLIENT_MODE)
|
||||
// Only clients support DialOnDemand. Maybe no change needed.
|
||||
if(Mode() != PPP_CLIENT_MODE || DoesDialOnDemand() == dialOnDemand)
|
||||
return;
|
||||
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
if(DoesDialOnDemand() && !dialondemand && State() != PPP_OPENED_STATE) {
|
||||
// as long as the protocols were not configured we can just delete us
|
||||
Delete();
|
||||
fDialOnDemand = dialOnDemand;
|
||||
|
||||
// Do not allow changes when we are disconnected (only main interfaces).
|
||||
// This would make no sense because
|
||||
// - enabling: this cannot happen because hidden interfaces are deleted if they
|
||||
// could not establish a connection (the user cannot access hidden interfaces)
|
||||
// - disabling: the interface disappears as seen from the user, so we delete it
|
||||
if(!Parent() && State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) {
|
||||
if(!dialOnDemand)
|
||||
Delete();
|
||||
// as long as the protocols were not configured we can just delete us
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fDialOnDemand = dialondemand;
|
||||
|
||||
// check if we need to register/unregister
|
||||
if(fDialOnDemand) {
|
||||
if(dialOnDemand) {
|
||||
RegisterInterface();
|
||||
if(Ifnet())
|
||||
Ifnet()->if_flags |= IFF_RUNNING;
|
||||
} else if(!fDialOnDemand && Phase() < PPP_ESTABLISHED_PHASE) {
|
||||
} else if(!dialOnDemand && Phase() < PPP_ESTABLISHED_PHASE) {
|
||||
UnregisterInterface();
|
||||
|
||||
// if we are already down we must delete us
|
||||
if(Phase() == PPP_DOWN_PHASE)
|
||||
if(State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE)
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
@@ -1414,7 +1422,6 @@ PPPInterface::RegisterInterface()
|
||||
return false;
|
||||
|
||||
CalculateBaudRate();
|
||||
SetupDialOnDemand();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1443,7 +1450,7 @@ PPPInterface::UnregisterInterface()
|
||||
}
|
||||
|
||||
|
||||
// stack routes ioctls to interface
|
||||
// called by PPPManager: manager routes stack ioctls to interface
|
||||
status_t
|
||||
PPPInterface::StackControl(uint32 op, void *data)
|
||||
{
|
||||
@@ -1452,75 +1459,59 @@ PPPInterface::StackControl(uint32 op, void *data)
|
||||
|
||||
switch(op) {
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
return StackControlEachHandler(op, data);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// used by ControlEachHandler()
|
||||
template<class T>
|
||||
class CallStackControl {
|
||||
public:
|
||||
inline CallStackControl(uint32 op, void *data, status_t& result)
|
||||
: fOp(op), fData(data), fResult(result) {}
|
||||
inline void operator() (T *item)
|
||||
{
|
||||
if(!item || !item->IsEnabled())
|
||||
return;
|
||||
status_t tmp = item->StackControl(fOp, fData);
|
||||
if(tmp == B_OK && fResult == B_BAD_VALUE)
|
||||
fResult = B_OK;
|
||||
else if(tmp != B_BAD_VALUE)
|
||||
fResult = tmp;
|
||||
}
|
||||
private:
|
||||
uint32 fOp;
|
||||
void *fData;
|
||||
status_t& fResult;
|
||||
};
|
||||
|
||||
// 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)
|
||||
PPPInterface::StackControlEachHandler(uint32 op, void *data)
|
||||
{
|
||||
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);
|
||||
tmp = encapsulator->StackControl(op, data);
|
||||
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;
|
||||
}
|
||||
ForEachItem(fProtocols, CallStackControl<PPPProtocol>(op, data, result));
|
||||
ForEachItem(LCP().fLCPExtensions,
|
||||
CallStackControl<PPPLCPExtension>(op, data, result));
|
||||
ForEachItem(LCP().fOptionHandlers,
|
||||
CallStackControl<PPPOptionHandler>(op, data, result));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1531,9 +1522,7 @@ PPPInterface::CalculateInterfaceMTU()
|
||||
{
|
||||
fInterfaceMTU = fMRU;
|
||||
|
||||
// sum all headers
|
||||
fHeaderLength = sizeof(uint16);
|
||||
|
||||
// sum all headers (the protocol field is not counted)
|
||||
PPPEncapsulator *encapsulator = fFirstEncapsulator;
|
||||
for(; encapsulator; encapsulator = encapsulator->Next())
|
||||
fHeaderLength += encapsulator->Overhead();
|
||||
@@ -1568,28 +1557,6 @@ PPPInterface::CalculateBaudRate()
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PPPInterface::SetupDialOnDemand()
|
||||
{
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
if(State() == PPP_OPENED_STATE)
|
||||
return true;
|
||||
|
||||
bool result = true;
|
||||
|
||||
PPPProtocol *protocol;
|
||||
for(int32 index = 0; index < CountProtocols(); index++) {
|
||||
protocol = ProtocolAt(index);
|
||||
if(protocol && protocol->IsEnabled())
|
||||
if(protocol->SetupDialOnDemand() != B_OK)
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PPPInterface::Redial(uint32 delay)
|
||||
{
|
||||
@@ -1660,10 +1627,22 @@ in_queue_thread(void *data)
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------
|
||||
// Function: interface_deleter_thread
|
||||
// ----------------------------------
|
||||
// The destructor is private, so this thread function cannot delete our interface.
|
||||
// To solve this problem we create a 'fake' class PPPManager (friend of PPPInterface)
|
||||
// which is only defined here (the real class is defined in the ppp_manager module).
|
||||
class PPPManager {
|
||||
public:
|
||||
PPPManager(PPPInterface *interface)
|
||||
{ if(interface) delete interface; }
|
||||
};
|
||||
|
||||
status_t
|
||||
interface_deleter_thread(void *data)
|
||||
{
|
||||
delete (PPPInterface*) data;
|
||||
PPPManager((PPPInterface*) data);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
#include <sys/socket.h>
|
||||
|
||||
|
||||
#define PPP_PROTOCOL_OVERHEAD 2
|
||||
|
||||
|
||||
PPPLCP::PPPLCP(PPPInterface& interface)
|
||||
: PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL,
|
||||
AF_UNSPEC, interface, NULL, PPP_ALWAYS_ALLOWED),
|
||||
@@ -177,7 +174,7 @@ PPPLCP::LCPExtensionFor(uint8 code, int32 *start = NULL) const
|
||||
uint32
|
||||
PPPLCP::AdditionalOverhead() const
|
||||
{
|
||||
uint32 overhead = PPP_PROTOCOL_OVERHEAD;
|
||||
uint32 overhead = 0;
|
||||
|
||||
if(Target())
|
||||
overhead += Target()->Overhead();
|
||||
|
||||
@@ -70,6 +70,18 @@ PPPLCPExtension::Control(uint32 op, void *data, size_t length)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPLCPExtension::StackControl(uint32 op, void *data)
|
||||
{
|
||||
switch(op) {
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PPPLCPExtension::Reset()
|
||||
{
|
||||
|
||||
@@ -68,3 +68,15 @@ PPPOptionHandler::Control(uint32 op, void *data, size_t length)
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPOptionHandler::StackControl(uint32 op, void *data)
|
||||
{
|
||||
switch(op) {
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -105,8 +105,13 @@ PPPProtocol::Control(uint32 op, void *data, size_t length)
|
||||
|
||||
|
||||
status_t
|
||||
PPPProtocol::SetupDialOnDemand()
|
||||
PPPProtocol::StackControl(uint32 op, void *data)
|
||||
{
|
||||
switch(op) {
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -313,7 +313,10 @@ PPPStateMachine::DownEvent(PPPInterface& interface)
|
||||
}
|
||||
}
|
||||
|
||||
Interface().SetMRU(MRU);
|
||||
if(MRU == 0)
|
||||
Interface().SetMRU(1500);
|
||||
else
|
||||
Interface().SetMRU(MRU);
|
||||
|
||||
if(count == 0) {
|
||||
locker.UnlockNow();
|
||||
@@ -1341,7 +1344,7 @@ PPPStateMachine::RCREvent(struct mbuf *packet)
|
||||
|
||||
result = handler->ParseRequest(request, index, nak, reject);
|
||||
|
||||
if(result != B_OK && result != PPP_UNHANDLED) {
|
||||
if(result != B_OK) {
|
||||
// the request contains a value that has been sent more than
|
||||
// once or the value is corrupted
|
||||
m_freem(packet);
|
||||
@@ -1359,7 +1362,7 @@ PPPStateMachine::RCREvent(struct mbuf *packet)
|
||||
result = handler->ParseRequest(request, request.CountItems(),
|
||||
nak, reject);
|
||||
|
||||
if(result != B_OK && result != PPP_UNHANDLED) {
|
||||
if(result != B_OK) {
|
||||
// the request contains a value that has been sent more than
|
||||
// once or the value is corrupted
|
||||
m_freem(packet);
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//
|
||||
// Copyright (c) 2003 Waldemar Kornewald, [email protected]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include "_KPPPMRUHandler.h"
|
||||
|
||||
#include <KPPPConfigurePacket.h>
|
||||
#include <KPPPDevice.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define MRU_TYPE 0x1
|
||||
|
||||
typedef struct mru_item {
|
||||
uint8 type;
|
||||
uint8 length;
|
||||
uint16 MRU;
|
||||
};
|
||||
|
||||
status_t ParseRequestedItem(mru_item *item, PPPInterface& interface);
|
||||
|
||||
|
||||
_PPPMRUHandler::_PPPMRUHandler(PPPInterface& interface)
|
||||
: PPPOptionHandler("MRU Handler", MRU_TYPE, interface, NULL)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_PPPMRUHandler::AddToRequest(PPPConfigurePacket& request)
|
||||
{
|
||||
if(!Interface().Device() || Interface().MRU() == 1500)
|
||||
return B_OK;
|
||||
|
||||
// add MRU request
|
||||
mru_item item;
|
||||
item.type = MRU_TYPE;
|
||||
item.length = 4;
|
||||
item.MRU = htons(fLocalMRU);
|
||||
return request.AddItem((ppp_configure_item*) &item) ? B_OK : B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_PPPMRUHandler::ParseNak(const PPPConfigurePacket& nak)
|
||||
{
|
||||
mru_item *item = (mru_item*) nak.ItemWithType(MRU_TYPE);
|
||||
if(!item || item->length != 4)
|
||||
return B_OK;
|
||||
|
||||
uint16 MRU = ntohs(item->MRU);
|
||||
if(MRU < fLocalMRU)
|
||||
fLocalMRU = MRU;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_PPPMRUHandler::ParseReject(const PPPConfigurePacket& reject)
|
||||
{
|
||||
if(reject.ItemWithType(MRU_TYPE))
|
||||
return B_ERROR;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_PPPMRUHandler::ParseAck(const PPPConfigurePacket& ack)
|
||||
{
|
||||
uint16 MRU = 1500;
|
||||
mru_item *item = (mru_item*) ack.ItemWithType(MRU_TYPE);
|
||||
|
||||
if(item)
|
||||
MRU = ntohs(item->MRU);
|
||||
|
||||
if(MRU < Interface().MRU())
|
||||
fLocalMRU = MRU;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_PPPMRUHandler::ParseRequest(const PPPConfigurePacket& request,
|
||||
int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject)
|
||||
{
|
||||
if(index == reject.CountItems())
|
||||
return B_OK;
|
||||
|
||||
return ParseRequestedItem((mru_item*) request.ItemAt(index), Interface());
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_PPPMRUHandler::SendingAck(const PPPConfigurePacket& ack)
|
||||
{
|
||||
return ParseRequestedItem((mru_item*) ack.ItemWithType(MRU_TYPE), Interface());
|
||||
}
|
||||
|
||||
|
||||
// this function contains code shared by ParseRequest and SendingAck
|
||||
status_t
|
||||
ParseRequestedItem(mru_item *item, PPPInterface& interface)
|
||||
{
|
||||
uint16 MRU = 1500;
|
||||
|
||||
if(item) {
|
||||
if(item->length != 4)
|
||||
return B_ERROR;
|
||||
// the request had a corrupted item
|
||||
|
||||
MRU = ntohs(item->MRU);
|
||||
}
|
||||
|
||||
if(MRU < interface.MRU())
|
||||
interface.SetMRU(MRU);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_PPPMRUHandler::Reset()
|
||||
{
|
||||
if(Interface().Device()) {
|
||||
fLocalMRU = Interface().Device()->MTU() - 2;
|
||||
Interface().SetMRU(fLocalMRU);
|
||||
} else {
|
||||
Interface().SetMRU(1500);
|
||||
fLocalMRU = 1500;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//
|
||||
// Copyright (c) 2003 Waldemar Kornewald, [email protected]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#ifndef __K_PPP_MRU_HANDLER__H
|
||||
#define __K_PPP_MRU_HANDLER__H
|
||||
|
||||
#include <KPPPOptionHandler.h>
|
||||
|
||||
|
||||
class _PPPMRUHandler : public PPPOptionHandler {
|
||||
public:
|
||||
_PPPMRUHandler(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:
|
||||
uint16 fLocalMRU;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user