Finished:

- PPPDevice
 - PPPEncapsulator
 - PPPOptionHandler
 - PPPProtocol

Added SendCodeReject implementation (though, I am not sure if it really works because I am not familiar with mbufs).

Fixed some bugs.
Changed the manager interface (there are no pointers to classes anymore).
Some minor changes.

TODO for libkernelppp.a:
- finish PPPLCP
- finish PPPConfigurePacket


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4400 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald
2003-08-29 12:57:59 +00:00
parent ba92606354
commit 3118bf2206
17 changed files with 693 additions and 134 deletions
@@ -44,7 +44,7 @@ class PPPConfigurePacket {
int32 CountItems() const; int32 CountItems() const;
configure_item *ItemAt(int32 index) const; configure_item *ItemAt(int32 index) const;
mbuf *ToMbuf(); mbuf *ToMbuf(uint32 reserve = 0, uint32 maxSize = 0);
// the user is responsible for freeing the mbuf // the user is responsible for freeing the mbuf
private: private:
+20 -14
View File
@@ -11,29 +11,35 @@
#include <Errors.h> #include <Errors.h>
typedef uint32 interface_id;
// various constants
#define PPP_PULSE_RATE 750000
// settings keys // settings keys
#define PPP_MODE_KEY "Mode" #define PPP_DISONNECT_AFTER_IDLE_SINCE_KEY "DisonnectAfterIdleSince"
#define PPP_DIAL_ON_DEMAND_KEY "DialOnDemand" #define PPP_MODE_KEY "Mode"
#define PPP_AUTO_REDIAL_KEY "AutoRedial" #define PPP_DIAL_ON_DEMAND_KEY "DialOnDemand"
#define PPP_LOAD_MODULE_KEY "LoadModule" #define PPP_AUTO_REDIAL_KEY "AutoRedial"
#define PPP_PROTOCOL_KEY "Protocol" #define PPP_LOAD_MODULE_KEY "LoadModule"
#define PPP_DEVICE_KEY "Device" #define PPP_PROTOCOL_KEY "Protocol"
#define PPP_AUTHENTICATOR_KEY "Authenticator" #define PPP_DEVICE_KEY "Device"
#define PPP_PEER_AUTHENTICATOR_KEY "Peer-Authenticator" #define PPP_AUTHENTICATOR_KEY "Authenticator"
#define PPP_MULTILINK_KEY "Multilink-Protocol" #define PPP_PEER_AUTHENTICATOR_KEY "Peer-Authenticator"
#define PPP_MULTILINK_KEY "Multilink-Protocol"
// settings values // settings values
#define PPP_CLIENT_MODE_VALUE "Client" #define PPP_CLIENT_MODE_VALUE "Client"
#define PPP_SERVER_MODE_VALUE "Server" #define PPP_SERVER_MODE_VALUE "Server"
// path defines // path defines
#define PPP_MODULES_PATH "network/ppp-modules" #define PPP_MODULES_PATH "network/ppp-modules"
// built-in protocols // built-in protocols
#define PPP_LCP_PROTOCOL 0xC021 #define PPP_LCP_PROTOCOL 0xC021
#define PPP_ERROR_BASE B_ERRORS_END #define PPP_ERROR_BASE B_ERRORS_END
// return values for Send()/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 // PPP_UNHANDLED is also used by PPPOptionHandler
+9 -7
View File
@@ -13,11 +13,11 @@
class PPPDevice { class PPPDevice {
public: public:
PPPDevice(const char *fName, uint32 overhead, PPPInterface *interface, PPPDevice(const char *name, uint32 overhead, PPPInterface *interface,
driver_parameter *settings); driver_parameter *settings);
virtual ~PPPDevice(); virtual ~PPPDevice();
virtual status_t InitCheck() const = 0; virtual status_t InitCheck() const;
const char *Name() const const char *Name() const
{ return fName; } { return fName; }
@@ -59,17 +59,19 @@ class PPPDevice {
// Do not call Interface::ReceiveFromDevice directly // Do not call Interface::ReceiveFromDevice directly
// if this can block a Send()! // if this can block a Send()!
virtual void Pulse();
protected: protected:
// Report that we are going up/down // Report that we are going up/down
// (from now on, the Up() process can be aborted). // (from now on, the Up() process can be aborted).
// Abort if false is returned! // Abort if false is returned!
bool UpStarted(); bool UpStarted() const;
bool DownStarted(); bool DownStarted() const;
// report up/down events // report up/down events
void UpEvent(); void UpFailedEvent() const;
void UpFailedEvent(); void UpEvent() const;
void DownEvent(); void DownEvent() const;
protected: protected:
bool fIsUp; bool fIsUp;
@@ -19,7 +19,7 @@ class PPPEncapsulator {
int32 flags = PPP_NO_FLAGS); int32 flags = PPP_NO_FLAGS);
virtual ~PPPEncapsulator(); virtual ~PPPEncapsulator();
virtual status_t InitCheck() const = 0; virtual status_t InitCheck() const;
const char *Name() const const char *Name() const
{ return fName; } { return fName; }
@@ -46,7 +46,8 @@ class PPPEncapsulator {
bool IsEnabled() const bool IsEnabled() const
{ return fEnabled; } { return fEnabled; }
void SetUpRequested(bool requested = true); void SetUpRequested(bool requested = true)
{ fUpRequested = requested; }
bool IsUpRequested() const bool IsUpRequested() const
{ return fUpRequested; } { return fUpRequested; }
@@ -71,11 +72,13 @@ class PPPEncapsulator {
virtual status_t Send(mbuf *packet, uint16 protocol) = 0; virtual status_t Send(mbuf *packet, uint16 protocol) = 0;
virtual status_t Receive(mbuf *packet, uint16 protocol) = 0; virtual status_t Receive(mbuf *packet, uint16 protocol) = 0;
status_t SendToNext(mbuf *packet, uint16 protocol); status_t SendToNext(mbuf *packet, uint16 protocol) const;
// this will send your packet to the next (up) encapsulator // this will send your packet to the next (up) encapsulator
// if there is no next encapsulator (==NULL), it will // if there is no next encapsulator (==NULL), it will
// call the interface's SendToDevice function // call the interface's SendToDevice function
virtual void Pulse();
protected: protected:
void UpStarted(); void UpStarted();
void DownStarted(); void DownStarted();
@@ -91,10 +94,11 @@ class PPPEncapsulator {
private: private:
char *fName; char *fName;
PPP_ENCAPSULATION_LEVEL fLevel; PPP_ENCAPSULATION_LEVEL fLevel;
uint16 fProtocol;
int32 fAddressFamily;
PPPInterface *fInterface; PPPInterface *fInterface;
driver_parameter *fSettings; driver_parameter *fSettings;
uint16 fProtocol; int32 fFlags;
int32 fAddressFamily, fFlags;
PPPEncapsulator *fNext; PPPEncapsulator *fNext;
+16 -2
View File
@@ -34,13 +34,17 @@ class PPPInterface {
PPPInterface& operator= (const PPPInterface& copy); PPPInterface& operator= (const PPPInterface& copy);
public: public:
PPPInterface(driver_settings *settings, PPPInterface *parent = NULL); PPPInterface(interface_id ID, driver_settings *settings,
PPPInterface *parent = NULL);
~PPPInterface(); ~PPPInterface();
void Delete(); void Delete();
status_t InitCheck() const; status_t InitCheck() const;
interface_id ID() const
{ return fID; }
driver_settings* Settings() driver_settings* Settings()
{ return fSettings; } { return fSettings; }
@@ -55,6 +59,12 @@ class PPPInterface {
struct ifq *InQueue() const struct ifq *InQueue() const
{ return fInQueue; } { return fInQueue; }
// idle handling
bigtime_t IdleSince() const
{ return fIdleSince; }
bigtime_t DisconnectAfterIdleSince() const
{ return fDisconnectAfterIdleSince; }
void SetLinkMTU(uint32 linkMTU); void SetLinkMTU(uint32 linkMTU);
uint32 LinkMTU() const uint32 LinkMTU() const
{ return fLinkMTU; } { return fLinkMTU; }
@@ -142,6 +152,7 @@ class PPPInterface {
bool UnregisterInterface(); bool UnregisterInterface();
void CalculateMRU(); void CalculateMRU();
void CalculateBaudRate();
void Redial(); void Redial();
@@ -150,7 +161,9 @@ class PPPInterface {
{ fParent = parent; } { fParent = parent; }
private: private:
driver_parameter *fSettings; interface_id fID;
// the manager assigns an ID to every interface
driver_settings *fSettings;
PPPStateMachine fStateMachine; PPPStateMachine fStateMachine;
PPPLCP fLCP; PPPLCP fLCP;
PPPReportManager fReportManager; PPPReportManager fReportManager;
@@ -164,6 +177,7 @@ class PPPInterface {
ppp_manager_info *fManager; ppp_manager_info *fManager;
bigtime_t fIdleSince, fDisconnectAfterIdleSince;
uint32 fLinkMTU, fMRU, fHeaderLength; uint32 fLinkMTU, fMRU, fHeaderLength;
PPPInterface *fParent; PPPInterface *fParent;
+5
View File
@@ -41,11 +41,16 @@ class PPPLCP : public PPPProtocol {
{ return fOptionHandlers.CountItems(); } { return fOptionHandlers.CountItems(); }
PPPOptionHandler *OptionHandlerAt(int32 index) const; PPPOptionHandler *OptionHandlerAt(int32 index) const;
PPPEncapsulator *Target() const
{ return fTarget; }
void SetTarget(PPPEncapsulator *target) void SetTarget(PPPEncapsulator *target)
{ fTarget = target; } { fTarget = target; }
// if target != all packtes will be passed to the encapsulator // if target != all packtes will be passed to the encapsulator
// instead of the interface/device // instead of the interface/device
uint32 AdditionalOverhead() const;
// the overhead caused by the target, the device, and the interface
private: private:
List<PPPOptionHandler*> fOptionHandlers; List<PPPOptionHandler*> fOptionHandlers;
+17 -12
View File
@@ -13,25 +13,30 @@
#define PPP_MANAGER_MODULE_NAME "network/interfaces/ppp" #define PPP_MANAGER_MODULE_NAME "network/interfaces/ppp"
// this allows you to ask for specific interface_ids
enum PPP_INTERFACE_FILTER {
PPP_ALL_INTERFACES,
PPP_REGISTERED_INTERFACES,
PPP_UNREGISTERED_INTERFACES
};
typedef struct ppp_manager_info { typedef struct ppp_manager_info {
kernel_net_module_info knminfo; kernel_net_module_info knminfo;
// when you want to iterate through interfaces you should use locking uint32 (*create_interface)(driver_settings *settings, interface_id parent);
void (*lock)(); // you should always create interfaces using this function
void (*unlock)(); void (*delete_interface)(interface_id ID);
// this marks the interface for deletion
ifnet* (*add_interface)(PPPInterface *interface); ifnet* (*register_interface)(interface_id ID);
bool (*remove_interface)(PPPInterface *interface); bool (*unregister_interface)(interface_id ID);
int32 (*count_interfaces)(int32 index); status_t (*control)(interface_id ID, uint32 op, void *data, size_t length);
PPPInterface *(*get_interface_at)(int32 index); status_t (*get_interfaces)(interface_id **interfaces, uint32 *count,
void (*put_interface)(PPPInterface *interface); PPP_INTERFACE_FILTER filter = PPP_REGISTERED_INTERFACES);
// the user is responsible for free()'ing the interface_id array
void (*delete_interface)(PPPInterface *interface); } ppp_manager_info;
// this deletes the interface when it is not needed anymore
} ppp_manager;
#endif #endif
@@ -18,7 +18,7 @@ class PPPOptionHandler {
driver_parameter *settings); driver_parameter *settings);
virtual ~PPPOptionHandler(); virtual ~PPPOptionHandler();
virtual status_t InitCheck() = 0; virtual status_t InitCheck() const;
void SetEnabled(bool enabled = true); void SetEnabled(bool enabled = true);
bool IsEnabled() const bool IsEnabled() const
@@ -18,7 +18,7 @@ class PPPProtocol {
driver_parameter *settings, int32 flags = PPP_NO_FLAGS); driver_parameter *settings, int32 flags = PPP_NO_FLAGS);
virtual ~PPPProtocol(); virtual ~PPPProtocol();
virtual status_t InitCheck() const = 0; virtual status_t InitCheck() const;
const char *Name() const const char *Name() const
{ return fName; } { return fName; }
@@ -41,7 +41,8 @@ class PPPProtocol {
bool IsEnabled() const bool IsEnabled() const
{ return fEnabled; } { return fEnabled; }
void SetUpRequested(bool requested = true); void SetUpRequested(bool requested = true)
{ fUpRequested = requested; }
bool IsUpRequested() const bool IsUpRequested() const
{ return fUpRequested; } { return fUpRequested; }
@@ -61,6 +62,8 @@ class PPPProtocol {
virtual status_t Send(mbuf *packet) = 0; virtual status_t Send(mbuf *packet) = 0;
virtual status_t Receive(mbuf *packet) = 0; virtual status_t Receive(mbuf *packet) = 0;
virtual void Pulse();
protected: protected:
void UpStarted(); void UpStarted();
void DownStarted(); void DownStarted();
@@ -74,9 +77,10 @@ class PPPProtocol {
char *name; char *name;
PPP_PHASE fPhase; PPP_PHASE fPhase;
uint16 fProtocol; uint16 fProtocol;
int32 fAddressFamily, fFlags; int32 fAddressFamily;
PPPInterface fInterface; PPPInterface fInterface;
driver_parameter fSettings; driver_parameter fSettings;
int32 fFlags;
bool fEnabled; bool fEnabled;
bool fUpRequested; bool fUpRequested;
@@ -26,7 +26,8 @@ enum PPP_REPORT_FLAGS {
enum PPP_REPORT_TYPE { enum PPP_REPORT_TYPE {
PPP_DESTRUCTION_REPORT = 0, PPP_DESTRUCTION_REPORT = 0,
// the interface is being destroyed (no code is needed) // the interface is being destroyed (no code is needed)
PPP_CONNECTION_REPORT = 1 PPP_CONNECTION_REPORT = 1,
PPP_AUTHENTICATION_REPORT = 2
}; };
// report codes (type-specific) // report codes (type-specific)
@@ -36,10 +37,13 @@ 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_FAILED = 5, PPP_REPORT_AUTHENTICATION_SUCCESSFUL = 5,
PPP_REPORT_CONNECTION_LOST = 6 PPP_REPORT_PEER_AUTHENTICATION_SUCCESSFUL = 6,
PPP_REPORT_AUTHENTICATION_FAILED = 7,
PPP_REPORT_CONNECTION_LOST = 8
}; };
typedef struct ppp_report_packet { typedef struct ppp_report_packet {
int32 type; int32 type;
int32 code; int32 code;
+124
View File
@@ -6,3 +6,127 @@
//--------------------------------------------------------------------- //---------------------------------------------------------------------
#include "KPPPDevice.h" #include "KPPPDevice.h"
PPPDevice::PPPDevice(const char *name, uint32 overhead, PPPInterface *interface,
driver_parameter *settings)
: fOverhead(overhead), fInterface(interface),
fSettings(settings)
{
fName = name ? strdup(name) : NULL;
SetMTU(PreferredMTU());
if(interface)
interface->SetDevice(this);
}
PPPDevice::~PPPDevice()
{
free(fName);
if(Interface())
Interface()->SetDevice(NULL);
}
status_t
PPPDevice::InitCheck() const
{
if(!Interface() || !Settings())
return B_ERROR;
return B_OK;
}
status_t
PPPDevice::Control(uint32 op, void *data, size_t length)
{
switch(op) {
// TODO:
// get:
// - name
// - mtu (+ preferred)
// - status
// - transfer rates
default:
return B_ERROR;
}
return B_OK;
}
status_t
PPPDevice::PassToInterface(mbuf *packet)
{
if(!Interface() || !Interface()->InQueue())
return B_ERROR;
IFQ_ENQUEUE(Interface()->InQueue(), packet);
}
void
PPPDevice::Pulse()
{
// do nothing by default
}
bool
PPPDevice::UpStarted() const
{
if(!Interface())
return false;
return Interface()->StateMachine().TLSNotify();
}
bool
PPPDevice::DownStarted() const
{
if(!Interface())
return false;
return Interface()->StateMachine().TLFNotify();
}
void
PPPDevice::UpFailedEvent()
{
fIsUp = false;
if(!Interface())
return;
Interface()->StateMachine().UpFailedEvent();
}
void
PPPDevice::UpEvent()
{
fIsUp = true;
if(!Interface())
return;
Interface()->StateMachine().UpEvent();
}
void
PPPDevice::DownEvent()
{
fIsUp = false;
if(!Interface())
return;
Interface()->StateMachine().DownEvent();
}
@@ -6,3 +6,143 @@
//--------------------------------------------------------------------- //---------------------------------------------------------------------
#include "KPPPEncapsulator.h" #include "KPPPEncapsulator.h"
PPPEncapsulator::PPPEncapsulator(const char *name, PPP_ENCAPSULATION_LEVEL level,
uint16 protocol, int32 addressFamily, uint32 overhead,
PPPInterface *interface, driver_parameter *settings,
int32 flags = PPP_NO_FLAGS)
: fOverhead(overhead), fLevel(level), fProtocol(protocol),
fAddressFamily(addressFamily), fInterface(interface),
fSettings(settings), fFlags(flags), fEnabled(true),
fUpRequested(true), fConnectionStatus(PPP_DOWN_PHASE)
{
fName = name ? strdup(name) : NULL;
if(interface)
interface->AddEncapsulator(this);
}
PPPEncapsulator::~PPPEncapsulator()
{
free(fName);
if(Interface())
Interface()->RemoveEncapsulator(this);
}
status_t
PPPEncapsulator::InitCheck() const
{
if(!Interface() || !Settings())
return B_ERROR;
return B_OK;
}
void
PPPEncapsulator::SetEnabled(bool enabled = true)
{
fEnabled = enabled;
if(!Interface())
return;
if(!enabled) {
if(IsUp() || IsGoingUp()))
Down();
} else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface()->IsUp())
Up();
}
status_t
PPPEncapsulator::Control(uint32 op, void *data, size_t length)
{
switch(op) {
// TODO:
// get:
// - name
// - level, protocol, address family, overhead
// - status (Is(Going)Up/Down/UpRequested/Enabled)
// set:
// - enabled
default:
return B_ERROR;
}
return B_OK;
}
status_t
PPPEncapsulator::SendToNext(mbuf *packet, uint16 protocol) const
{
if(Next())
return Next()->Send(packet, protocol);
else if(Interface())
return Interface()->SendToDevice(packet, protocol);
else
return B_ERROR;
}
void
PPPEncapsulator::Pulse()
{
// do nothing by default
}
void
PPPEncapsulator::UpStarted()
{
fConnectionStatus = PPP_ESTABLISHMENT_PHASE;
}
void
PPPEncapsulator::DownStarted()
{
fConnectionStatus = PPP_TERMINATION_PHASE;
}
void
PPPEncapsulator::UpFailedEvent()
{
fConnectionStatus = PPP_DOWN_PHASE;
if(!Interface())
return;
Interface()->StateMachine().UpFailedEvent(this);
}
void
PPPEncapsulator::UpEvent()
{
fConnectionStatus = PPP_ESTABLISHED_PHASE;
if(!Interface())
return;
Interface()->StateMachine().UpEvent(this);
}
void
PPPEncapsulator::DownEvent()
{
fConnectionStatus = PPP_DOWN_PHASE;
if(!Interface())
return;
Interface()->StateMachine().DownEvent(this);
}
+93 -59
View File
@@ -12,7 +12,6 @@
#include "KPPPManager.h" #include "KPPPManager.h"
// general helper classes not only belonging to us // general helper classes not only belonging to us
#include "AccessHelper.h"
#include "LockerHelper.h" #include "LockerHelper.h"
// tools only for us :) // tools only for us :)
@@ -43,13 +42,15 @@ status_t redial_func(void *data);
status_t in_queue_thread(void *data); status_t in_queue_thread(void *data);
PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NULL) PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
: fSettings(dup_driver_settings(settings)), PPPInterface *parent = NULL)
: fID(ID), fSettings(dup_driver_settings(settings)),
fStateMachine(*this), fLCP(*this), ReportManager()(StateMachine().Locker()), fStateMachine(*this), fLCP(*this), ReportManager()(StateMachine().Locker()),
fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0), fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0),
fDialRetriesLimit(0), fLinkMTU(1500), fAccessing(0), fChildrenCount(0), fDialRetriesLimit(0), fIdleSince(0), fLinkMTU(1500), fDevice(NULL),
fDevice(NULL), fFirstEncapsulator(NULL), fLock(StateMachine().Locker()) fFirstEncapsulator(NULL), fLock(StateMachine().Locker())
{ {
// set up queue
fInQueue = start_ifq(); fInQueue = start_ifq();
fInQueueThread = spawn_kernel_thread(in_queue_thread, "PPPInterface: Input", fInQueueThread = spawn_kernel_thread(in_queue_thread, "PPPInterface: Input",
B_NORMAL_PRIORITY, this); B_NORMAL_PRIORITY, this);
@@ -61,17 +62,32 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL
// are we a multilink subinterface? // are we a multilink subinterface?
if(parent && parent->IsMultilink()) { if(parent && parent->IsMultilink()) {
fParent = parent; fParent = parent;
fParent->AddChild(this);
fIsMultilink = true; fIsMultilink = true;
} else { } else {
fParent = NULL; fParent = NULL;
fIsMultilink = false; fIsMultilink = false;
} }
if(!fSettings) if(!fSettings) {
fMode = PPP_CLIENT_MODE;
fDisconnectAfterIdleSince = 0;
return; return;
}
const char *value; const char *value;
// get DisonnectAfterIdleSince settings
value = get_settings_value(PPP_DISONNECT_AFTER_IDLE_SINCE_KEY, fSettings);
if(!value)
fDisconnectAfterIdleSince = 0;
else
fDisconnectAfterIdleSince = atoi(value);
if(fDisconnectAfterIdleSince < 0)
fDisconnectAfterIdleSince = 0;
// get mode settings
value = get_settings_value(PPP_MODE_KEY, fSettings); value = get_settings_value(PPP_MODE_KEY, fSettings);
if(!strcasecmp(value, PPP_SERVER_MODE_VALUE)) if(!strcasecmp(value, PPP_SERVER_MODE_VALUE))
fMode = PPP_SERVER_MODE; fMode = PPP_SERVER_MODE;
@@ -132,7 +148,7 @@ PPPInterface::~PPPInterface()
void void
PPPInterface::Delete() PPPInterface::Delete()
{ {
fManager->delete_interface(this); fManager->delete_interface(ID());
} }
@@ -177,7 +193,7 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
default: default:
return B_ERROR; return B_ERROR;
} }
return B_OK; return B_OK;
@@ -206,11 +222,9 @@ PPPInterface::SetDevice(PPPDevice *device)
fDevice = device; fDevice = device;
fLinkMTU = fDevice->MTU(); fLinkMTU = fDevice->MTU();
if(Ifnet())
Ifnet()->if_baudrate = max(fDevice->InputTransferRate(),
fDevice->OutputTransferRate());
CalculateMRU(); CalculateMRU();
CalculateBaudRate();
} }
@@ -407,9 +421,7 @@ PPPInterface::RemoveChild(PPPInterface *child)
// parents cannot exist without their children // parents cannot exist without their children
if(CountChildren() == 0 && fManager && Ifnet()) if(CountChildren() == 0 && fManager && Ifnet())
fManager->delete_interface(this); fManager->delete_interface(ID());
CalculateMRU();
return true; return true;
} }
@@ -534,7 +546,7 @@ PPPInterface::Up()
fUpThread = -1; fUpThread = -1;
if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL) if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL)
fManager->delete_interface(this); fManager->delete_interface(ID());
} }
PPP_REPLY(sender, B_OK); PPP_REPLY(sender, B_OK);
@@ -572,7 +584,7 @@ PPPInterface::Up()
if(!DoesDialOnDemand() if(!DoesDialOnDemand()
&& report.code != PPP_REPORT_DOWN_SUCCESSFUL) && report.code != PPP_REPORT_DOWN_SUCCESSFUL)
fManager->delete_interface(this); fManager->delete_interface(ID());
PPP_REPLY(sender, B_OK); PPP_REPLY(sender, B_OK);
ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); ReportManager().DisableReports(PPP_CONNECTION_REPORT, me);
@@ -599,12 +611,15 @@ PPPInterface::Up()
if(!DoesDialOnDemand() if(!DoesDialOnDemand()
&& report.code != PPP_REPORT_DOWN_SUCCESSFUL) && report.code != PPP_REPORT_DOWN_SUCCESSFUL)
fManager->delete_interface(this); fManager->delete_interface(ID());
return false; return false;
} }
} }
} }
// if the code is unknown we continue
PPP_REPLY(sender, B_OK);
} }
return false; return false;
@@ -644,7 +659,7 @@ PPPInterface::Down()
} }
if(!DoesDialOnDemand()) if(!DoesDialOnDemand())
fManager->delete_interface(this); fManager->delete_interface(ID());
return true; return true;
} }
@@ -674,12 +689,11 @@ PPPInterface::LoadModules(const driver_settings *settings,
// multilink handling // multilink handling
for(int32 i = start; for(int32 i = start;
i < settings->parameter_count && i < start + count; i < settings->parameter_count && i < start + count; i++) {
i++) {
if(!strcasecmp(settings->parameters[i].name, PPP_MULTILINK_KEY) if(!strcasecmp(settings->parameters[i].name, PPP_MULTILINK_KEY)
&& settings->parameters[i].value_count > 0) { && settings->parameters[i].value_count > 0) {
if(!LoadModule(settings->parameters[i].value[0], if(!LoadModule(settings->parameters[i].value[0],
parameters[i].parameters, PPP_MULTILINK_TYPE)) parameters[i].parameters, PPP_MULTILINK_TYPE))
return false; return false;
break; break;
} }
@@ -690,14 +704,12 @@ PPPInterface::LoadModules(const driver_settings *settings,
if(IsMultilink() && !Parent()) { if(IsMultilink() && !Parent()) {
// main interfaces only load the multilink module // main interfaces only load the multilink module
// and create a child using their settings // and create a child using their settings
AddChild(new PPPInterface(settings, this)); fManager->create_interface(settings, ID());
return true; return true;
} }
for(int32 i = start; for(int32 i = start;
i < settings->parameter_count && i < start + count; i < settings->parameter_count && i < start + count; i++) {
i++) {
type = -1; type = -1;
name = settings->parameters[i].name; name = settings->parameters[i].name;
@@ -715,9 +727,9 @@ PPPInterface::LoadModules(const driver_settings *settings,
if(type >= 0) if(type >= 0)
for(int32 value_id = 0; value_id < settings->parameters[i].value_count; for(int32 value_id = 0; value_id < settings->parameters[i].value_count;
value_id++) value_id++)
if(!LoadModule(settings->parameters[i].value[value_id], if(!LoadModule(settings->parameters[i].value[value_id],
settings->parameters[i].parameters, type)) settings->parameters[i].parameters, type))
return false; return false;
} }
@@ -756,8 +768,6 @@ PPPInterface::LoadModule(const char *name, const driver_parameter *parameter,
status_t status_t
PPPInterface::Send(mbuf *packet, uint16 protocol) PPPInterface::Send(mbuf *packet, uint16 protocol)
{ {
AccessHelper access(&fAccessing);
if(!packet) if(!packet)
return B_ERROR; return B_ERROR;
@@ -781,8 +791,10 @@ PPPInterface::Send(mbuf *packet, uint16 protocol)
// Note that these protocols are not passed to encapsulators! // Note that these protocols are not passed to encapsulators!
PPPProtocol *sending_protocol = ProtocolFor(protocol); PPPProtocol *sending_protocol = ProtocolFor(protocol);
if(sending_protocol && sending_protocol->Flags() & PPP_ALWAYS_ALLOWED if(sending_protocol && sending_protocol->Flags() & PPP_ALWAYS_ALLOWED
&& sending_protocol->IsEnabled() && fDevice->IsUp()) && sending_protocol->IsEnabled() && fDevice->IsUp()) {
fIdleSince = system_time();
return SendToDevice(packet, protocol); return SendToDevice(packet, protocol);
}
// never send normal protocols when we are down // never send normal protocols when we are down
if(!IsUp()) { if(!IsUp()) {
@@ -790,6 +802,8 @@ PPPInterface::Send(mbuf *packet, uint16 protocol)
return B_ERROR; return B_ERROR;
} }
fIdleSince = system_time();
// send to next up encapsulator // send to next up encapsulator
if(!fFirstEncapsulator) if(!fFirstEncapsulator)
return SendToDevice(packet, protocol); return SendToDevice(packet, protocol);
@@ -804,8 +818,6 @@ PPPInterface::Send(mbuf *packet, uint16 protocol)
status_t status_t
PPPInterface::Receive(mbuf *packet, uint16 protocol) PPPInterface::Receive(mbuf *packet, uint16 protocol)
{ {
AccessHelper access(&fAccessing);
if(!packet) if(!packet)
return B_ERROR; return B_ERROR;
@@ -874,8 +886,6 @@ PPPInterface::Receive(mbuf *packet, uint16 protocol)
status_t status_t
PPPInterface::SendToDevice(mbuf *packet, uint16 protocol) PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
{ {
AccessHelper access(&fAccessing);
if(!packet) if(!packet)
return B_ERROR; return B_ERROR;
@@ -914,7 +924,7 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
} }
// encode in ppp frame // encode in ppp frame
packet = M_PREPEND(packet, sizeof(uint16)); M_PREPEND(packet, sizeof(uint16));
if(packet == NULL) if(packet == NULL)
return B_ERROR; return B_ERROR;
@@ -924,11 +934,13 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
uint16 *header = mtod(packet, uint16*); uint16 *header = mtod(packet, uint16*);
*header = protocol; *header = protocol;
fIdleSince = system_time();
// pass to device/children // pass to device/children
if(!IsMultilink() || Parent()) { if(!IsMultilink() || Parent()) {
// check if packet is too big for device // check if packet is too big for device
if((packet->m_flags & M_PKTHDR && packet->m_pkt_hdr.len > LinkMTU()) if((packet->m_flags & M_PKTHDR && packet->m_pkthdr.len > LinkMTU())
|| packet->m_len > LinkMTU()) { || packet->m_len > LinkMTU()) {
m_freem(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
@@ -945,8 +957,6 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
status_t status_t
PPPInterface::ReceiveFromDevice(mbuf *packet) PPPInterface::ReceiveFromDevice(mbuf *packet)
{ {
AccessHelper access(&fAccessing);
if(!packet) if(!packet)
return B_ERROR; return B_ERROR;
@@ -961,16 +971,12 @@ PPPInterface::ReceiveFromDevice(mbuf *packet)
m_adj(packet, sizeof(uint16)); m_adj(packet, sizeof(uint16));
if(packet->m_flags & M_PKTHDR) { // Set our interface as the receiver.
// This might be NULL, so protocols that belong to the network stack (IP, etc.)
// will probably be confused (as there is no interface from which the packet came).
// Protocols that live only in the PPP interface should have no problems with this.
if(packet->m_flags & M_PKTHDR)
packet->m_pkthdr.rcvif = Ifnet(); packet->m_pkthdr.rcvif = Ifnet();
// make sure the protocols think we received
// the packet
if(!packet->m_pkthdr.rcvif) {
m_freem(packet);
return B_ERROR;
}
}
return Receive(packet, protocol); return Receive(packet, protocol);
} }
@@ -979,10 +985,24 @@ PPPInterface::ReceiveFromDevice(mbuf *packet)
void void
PPPInterface::Pulse() PPPInterface::Pulse()
{ {
// TODO: // check our idle time and disconnect if needed
// check our idle time if(fDisconnectAfterIdleSince > 0 && fIdleSince != 0
&& fIdleSince - system_time() >= fDisconnectAfterIdleSince) {
StateMachine().CloseEvent();
return;
}
StateMachine().TimerEvent(); StateMachine().TimerEvent();
if(Device())
Device()->Pulse();
for(int32 index = 0; index < CountProtocols(); index++)
ProtocolAt(index)->Pulse();
PPPEncapsulator *encapsulator = fFirstEncapsulator;
for(; encapsulator; encapsulator = encapsulator->Next())
encapsulator->Pulse();
} }
@@ -1004,14 +1024,12 @@ PPPInterface::RegisterInterface()
if(!fManager) if(!fManager)
return false; return false;
fIfnet = fManager->add_interface(this); fIfnet = fManager->register_interface(ID());
if(!fIfnet) if(!fIfnet)
return false; return false;
if(Device()) CalculateBaudRate();
fIfnet->if_baudrate = max(Device()->InputTransferRate(),
Device()->OutputTransferRate());
return true; return true;
} }
@@ -1031,7 +1049,7 @@ PPPInterface::UnregisterInterface()
if(!fManager) if(!fManager)
return false; return false;
fManager->remove_interface(this); fManager->unregister_interface(ID());
fIfnet = NULL; fIfnet = NULL;
return true; return true;
@@ -1047,10 +1065,8 @@ PPPInterface::CalculateMRU()
fHeaderLength = sizeof(uint16); fHeaderLength = sizeof(uint16);
PPPEncapsulator encapsulator = fFirstEncapsulator; PPPEncapsulator encapsulator = fFirstEncapsulator;
while(encapsulator) { for(; encapsulator; encapsulator = encapsulator->Next())
fHeaderLength += encapsulator->Overhead(); fHeaderLength += encapsulator->Overhead();
encapsulator = encapsulator->Next();
}
fMRU -= fHeaderLength; fMRU -= fHeaderLength;
@@ -1064,6 +1080,24 @@ PPPInterface::CalculateMRU()
} }
void
PPPInterface::CalculateBaudRate()
{
if(!Ifnet())
return;
if(Device())
fIfnet->if_baudrate = max(Device()->InputTransferRate(),
Device()->OutputTransferRate());
else {
fIfnet->if_baudrate = 0;
for(int32 index = 0; index < CountChildren(); index++)
if(ChildAt(index)->Ifnet())
fIfnet->if_baudrate += ChildAt(index)->Ifnet()->if_baudrate;
}
}
void void
PPPInterface::Redial() PPPInterface::Redial()
{ {
+13
View File
@@ -64,3 +64,16 @@ PPPLCP::OptionHandlerAt(int32 index) const
return handler; return handler;
} }
uint32
PPPLCP::AdditionalOverhead const
{
uint32 overhead += PPP_PROTOCOL_OVERHEAD;
if(Target())
overhead += Target()->Overhead();
if(Interface()->Device())
overhead += Interface()->Device()->Overhead();
return overhead;
}
@@ -6,3 +6,33 @@
//--------------------------------------------------------------------- //---------------------------------------------------------------------
#include "KPPPOptionHandler.h" #include "KPPPOptionHandler.h"
PPPOptionHandler::PPPOptionHandler(const char *name, PPPInterface *interface,
driver_parameter *settings)
: fInterface(interface), fSettings(settings)
{
fName = name ? strdup(name) : NULL;
if(interface)
interface->LCP().AddOptionHandler(this);
}
PPPOptionHandler::~PPPOptionHandler()
{
free(fName);
if(Interface())
Interface()->LCP().RemoveOptionHandler(this);
}
status_t
PPPOptionHandler::InitCheck() const
{
if(!Interface() || !Settings())
return B_ERROR;
return B_OK;
}
+126
View File
@@ -6,3 +6,129 @@
//--------------------------------------------------------------------- //---------------------------------------------------------------------
#include "KPPPProtocol.h" #include "KPPPProtocol.h"
PPPProtocol::PPPProtocol(const char *name, PPP_PHASE phase, uint16 protocol,
int32 addressFamily, PPPInterface *interface,
driver_parameter *settings, int32 flags = PPP_NO_FLAGS)
: fPhase(phase), fProtocol(protocol), fAddressFamily(addressFamily),
fInterface(interface), fSettings(settings), fFlags(flags),
fEnabled(true), fUpRequested(true), fConnectionStatus(PPP_DOWN_PHASE)
{
fName = name ? strdup(name) : NULL;
if(interface)
interface->AddProtocol(this);
}
PPPProtocol::~PPPProtocol()
{
free(fName);
if(Interface())
Interface()->RemoveProtocol(this);
}
status_t
PPPProtocol::InitCheck() const
{
if(!Interface() || !Settings())
return B_ERROR;
return B_OK;
}
void
PPPProtocol::SetEnabled(bool enabled = true)
{
fEnabled = enabled;
if(!Interface())
return;
if(!enabled) {
if(IsUp() || IsGoingUp()))
Down();
} else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface()->IsUp())
Up();
}
status_t
PPPProtocol::Control(uint32 op, void *data, size_t length)
{
switch(op) {
// TODO:
// get:
// - name
// - protocol, address family
// - status (Is(Going)Up/Down/UpRequested/Enabled)
// set:
// - enabled
default:
return B_ERROR;
}
return B_OK;
}
void
PPPProtocol::Pulse()
{
// do nothing by default
}
void
PPPProtocol::UpStarted()
{
fConnectionStatus = PPP_ESTABLISHMENT_PHASE;
}
void
PPPProtocol::DownStarted()
{
fConnectionStatus = PPP_TERMINATION_PHASE;
}
void
PPPProtocol::UpFailedEvent()
{
fConnectionStatus = PPP_DOWN_PHASE;
if(!Interface())
return;
Interface()->StateMachine().UpFailedEvent(this);
}
void
PPPProtocol::UpEvent()
{
fConnectionStatus = PPP_ESTABLISHED_PHASE;
if(!Interface())
return;
Interface()->StateMachine().UpEvent(this);
}
void
PPPProtocol::DownEvent()
{
fConnectionStatus = PPP_DOWN_PHASE;
if(!Interface())
return;
Interface()->StateMachine().DownEvent(this);
}
+75 -27
View File
@@ -105,6 +105,8 @@ PPPStateMachine::AuthenticationAccepted(const char *name)
fAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL; fAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL;
free(fAuthenticationName); free(fAuthenticationName);
fAuthenticationName = strdup(name); fAuthenticationName = strdup(name);
Interface()->Report(PPP_CONNECTION_REPORT, PPP_REPORT_AUTHENTICATION_SUCCESSFUL, 0);
} }
@@ -147,6 +149,9 @@ PPPStateMachine::PeerAuthenticationAccepted(const char *name)
fPeerAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL; fPeerAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL;
free(fPeerAuthenticationName); free(fPeerAuthenticationName);
fPeerAuthenticationName = strdup(name); fPeerAuthenticationName = strdup(name);
Interface()->Report(PPP_CONNECTION_REPORT,
PPP_REPORT_PEER_AUTHENTICATION_SUCCESSFUL, 0);
} }
@@ -183,17 +188,23 @@ PPPStateMachine::UpEvent(PPPInterface *interface)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
if(Phase() <= PPP_TERMINATION_PHASE || State() != PPP_STARTING_STATE) { if(Phase() <= PPP_TERMINATION_PHASE) {
interface->StateMachine().CloseEvent(); interface->StateMachine().CloseEvent();
return; return;
} }
NewState(PPP_OPENED_STATE); Interface()->CalculateBaudRate();
if(Phase() == PPP_ESTABLISHMENT_PHASE) { if(Phase() == PPP_ESTABLISHMENT_PHASE) {
NewPhase(PPP_AUTHENTICATION_PHASE); // this is the first interface that went up
Interface()->SetLinkMTU(interface->LinkMTU());
locker.UnlockNow(); locker.UnlockNow();
ThisLayerUp(); ThisLayerUp();
} } else if(Interface()->LinkMTU() > interface->LinkMTU())
Interface()->SetLinkMTU(interface->LinkMTU());
// linkMTU should always be the smallest value of all children
NewState(PPP_OPENED_STATE);
} }
@@ -202,6 +213,11 @@ PPPStateMachine::DownEvent(PPPInterface *interface)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
uint32 linkMTU = 0;
// the new linkMTU
Interface()->CalculateBaudRate();
// when all children are down we should not be running // when all children are down we should not be running
if(Interface()->IsMultilink() && !Interface()->Parent()) { if(Interface()->IsMultilink() && !Interface()->Parent()) {
uint32 count = 0; uint32 count = 0;
@@ -209,10 +225,19 @@ PPPStateMachine::DownEvent(PPPInterface *interface)
for(int32 index = 0; index < Interface()->CountChildren(); index++) { for(int32 index = 0; index < Interface()->CountChildren(); index++) {
child = Interface()->ChildAt(index); child = Interface()->ChildAt(index);
if(child && child->IsUp()) if(child && child->IsUp()) {
// set linkMTU to the smallest value of all children
if(linkMTU == 0)
linkMTU = child->LinkMTU();
else if(linkMTU > child->LinkMTU())
linkMTU = child->LinkMTU();
++count; ++count;
}
} }
Interface()->SetLinkMTU(linkMTU);
if(count == 0) { if(count == 0) {
locker.UnlockNow(); locker.UnlockNow();
DownEvent(); DownEvent();
@@ -372,10 +397,7 @@ PPPStateMachine::UpEvent()
return; return;
// it is not our device that went up... // it is not our device that went up...
if(Interface()->Ifnet()) Interface()->CalculateBaudRate();
Interface()->Ifnet()->if_baudrate = max(
Interface()->Device()->InputTransferRate(),
Interface()->Device()->OutputTransferRate());
switch(State()) { switch(State()) {
case PPP_INITIAL_STATE: case PPP_INITIAL_STATE:
@@ -428,14 +450,14 @@ PPPStateMachine::DownEvent()
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
if(!Interface()->Device() || Interface()->Device->IsUp()) if(Interface()->Device() && Interface()->Device->IsUp())
return; return;
// it is not our device that went up... // it is not our device that went up...
if(Interface()->Ifnet()) Interface()->CalculateBaudRate();
Interface()->Ifnet()->if_baudrate = max(
Interface()->Device()->InputTransferRate(), // reset IdleSince
Interface()->Device()->OutputTransferRate()); Interface()->fIdleSince = 0;
switch(State()) { switch(State()) {
case PPP_CLOSED_STATE: case PPP_CLOSED_STATE:
@@ -1150,7 +1172,7 @@ PPPStateMachine::RCREvent(mbuf *packet)
handled = false; handled = false;
for(int32 index = 0; index < LCP().CountOptionHandlers(); for(int32 index = 0; index < LCP().CountOptionHandlers();
index++) { index++) {
handler = LCP().OptionHandlerAt(index); handler = LCP().OptionHandlerAt(index);
error = handler->ParseRequest(&request, item, &nak, &reject); error = handler->ParseRequest(&request, item, &nak, &reject);
if(error == PPP_UNHANLED) if(error == PPP_UNHANLED)
@@ -1171,9 +1193,9 @@ PPPStateMachine::RCREvent(mbuf *packet)
} }
if(nak.CountItems() > 0) if(nak.CountItems() > 0)
RCRBadEvent(nak.ToMbuf(), NULL); RCRBadEvent(nak.ToMbuf(LCP().AdditionalOverhead()), NULL);
else if(reject.CountItmes() > 0) else if(reject.CountItmes() > 0)
RCRBadEvent(NULL, reject.ToMbuf()); RCRBadEvent(NULL, reject.ToMbuf(LCP().AdditionalOverhead()));
else else
RCRGoodEvent(packet); RCRGoodEvent(packet);
} }
@@ -1326,7 +1348,7 @@ PPPStateMachine::SendConfigureRequest()
} }
} }
LCP().Send(request.ToMbuf()); LCP().Send(request.ToMbuf(LCP().AdditionalOverhead()));
} }
@@ -1369,11 +1391,7 @@ PPPStateMachine::SendTerminateRequest()
--fTerminateCounter; --fTerminateCounter;
// reserve some space for other protocols // reserve some space for other protocols
m->m_data += PPP_PROTOCOL_OVERHEAD; m->m_data += LCP().AdditionalOverhead();
if(LCP().Encapsulator())
m->m_data += LCP().Encapsulator()->Overhead();
if(Interface()->Device())
m->m_data += Interface()->Device()->Overhead();
lcp_packet *request = mtod(m, lcp_packet*); lcp_packet *request = mtod(m, lcp_packet*);
request->code = PPP_TERMINATE_REQUEST; request->code = PPP_TERMINATE_REQUEST;
@@ -1398,8 +1416,36 @@ PPPStateMachine::SendTerminateAck(mbuf *request)
void void
PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol, uint8 type) PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol, uint8 type)
{ {
// TODO: int32 length;
// add the packet to the reject and truncate it if needed // additional space needed for this reject
if(type == PPP_PROTOCOL_REJECT)
length = 6;
else
length = 4;
M_PREPEND(packet, length + LCP().AdditionalOverhead());
int32 adjust = 0;
// adjust packet size by this value if packet is too big
if(packet->m_flags & M_PKTHDR) {
if(packet->m_pkthdr.len > Interface()->LinkMTU())
adjust = Interface()->LinkMTU() - packet->m_pkthdr.len;
} else if(packet->m_len > Interface()->LinkMTU())
adjust = Interface()->LinkMTU() - packet->m_len;
if(adjust != 0)
m_adj(packet, adjust);
lcp_packet *reject = mtod(packet, lcp_packet*);
data->code = type;
data->id = NextID();
data->length = (uint16) htons(reject->m_pkthdr.len);
protocol = (uint16) htons(protocol);
if(type == PPP_PROTOCOL_REJECT)
memcpy(&data->data, &protocol, sizeof(protocol));
LCP().Send(packet);
} }
@@ -1483,7 +1529,8 @@ void
PPPStateMachine::DownProtocols() PPPStateMachine::DownProtocols()
{ {
for(int32 index = 0; index < Interface()->CountProtocols(); index++) for(int32 index = 0; index < Interface()->CountProtocols(); index++)
Interface()->ProtocolAt(index)->Down(); if(Interface()->ProtocolAt(index)->IsEnabled())
Interface()->ProtocolAt(index)->Down();
} }
@@ -1494,7 +1541,8 @@ PPPStateMachine::DownEncapsulators()
for(; encapsulator_handler; for(; encapsulator_handler;
encapsulator_handler = encapsulator_handler->Next()) encapsulator_handler = encapsulator_handler->Next())
encapsualtor_handler->Down(); if(encapsulator_handler->IsEnabled())
encapsualtor_handler->Down();
} }