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

View File

@ -44,7 +44,7 @@ class PPPConfigurePacket {
int32 CountItems() 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
private:

View File

@ -11,29 +11,35 @@
#include <Errors.h>
typedef uint32 interface_id;
// various constants
#define PPP_PULSE_RATE 750000
// settings keys
#define PPP_MODE_KEY "Mode"
#define PPP_DIAL_ON_DEMAND_KEY "DialOnDemand"
#define PPP_AUTO_REDIAL_KEY "AutoRedial"
#define PPP_LOAD_MODULE_KEY "LoadModule"
#define PPP_PROTOCOL_KEY "Protocol"
#define PPP_DEVICE_KEY "Device"
#define PPP_AUTHENTICATOR_KEY "Authenticator"
#define PPP_PEER_AUTHENTICATOR_KEY "Peer-Authenticator"
#define PPP_MULTILINK_KEY "Multilink-Protocol"
#define PPP_DISONNECT_AFTER_IDLE_SINCE_KEY "DisonnectAfterIdleSince"
#define PPP_MODE_KEY "Mode"
#define PPP_DIAL_ON_DEMAND_KEY "DialOnDemand"
#define PPP_AUTO_REDIAL_KEY "AutoRedial"
#define PPP_LOAD_MODULE_KEY "LoadModule"
#define PPP_PROTOCOL_KEY "Protocol"
#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"
#define PPP_SERVER_MODE_VALUE "Server"
#define PPP_CLIENT_MODE_VALUE "Client"
#define PPP_SERVER_MODE_VALUE "Server"
// path defines
#define PPP_MODULES_PATH "network/ppp-modules"
#define PPP_MODULES_PATH "network/ppp-modules"
// 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
// PPP_UNHANDLED is also used by PPPOptionHandler

View File

@ -13,11 +13,11 @@
class PPPDevice {
public:
PPPDevice(const char *fName, uint32 overhead, PPPInterface *interface,
PPPDevice(const char *name, uint32 overhead, PPPInterface *interface,
driver_parameter *settings);
virtual ~PPPDevice();
virtual status_t InitCheck() const = 0;
virtual status_t InitCheck() const;
const char *Name() const
{ return fName; }
@ -58,18 +58,20 @@ class PPPDevice {
// This will pass the packet to the interface's queue.
// Do not call Interface::ReceiveFromDevice directly
// if this can block a Send()!
virtual void Pulse();
protected:
// 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();
bool UpStarted() const;
bool DownStarted() const;
// report up/down events
void UpEvent();
void UpFailedEvent();
void DownEvent();
void UpFailedEvent() const;
void UpEvent() const;
void DownEvent() const;
protected:
bool fIsUp;

View File

@ -19,7 +19,7 @@ class PPPEncapsulator {
int32 flags = PPP_NO_FLAGS);
virtual ~PPPEncapsulator();
virtual status_t InitCheck() const = 0;
virtual status_t InitCheck() const;
const char *Name() const
{ return fName; }
@ -46,7 +46,8 @@ class PPPEncapsulator {
bool IsEnabled() const
{ return fEnabled; }
void SetUpRequested(bool requested = true);
void SetUpRequested(bool requested = true)
{ fUpRequested = requested; }
bool IsUpRequested() const
{ return fUpRequested; }
@ -71,10 +72,12 @@ class PPPEncapsulator {
virtual status_t Send(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
// if there is no next encapsulator (==NULL), it will
// call the interface's SendToDevice function
virtual void Pulse();
protected:
void UpStarted();
@ -91,10 +94,11 @@ class PPPEncapsulator {
private:
char *fName;
PPP_ENCAPSULATION_LEVEL fLevel;
uint16 fProtocol;
int32 fAddressFamily;
PPPInterface *fInterface;
driver_parameter *fSettings;
uint16 fProtocol;
int32 fAddressFamily, fFlags;
int32 fFlags;
PPPEncapsulator *fNext;

View File

@ -34,13 +34,17 @@ class PPPInterface {
PPPInterface& operator= (const PPPInterface& copy);
public:
PPPInterface(driver_settings *settings, PPPInterface *parent = NULL);
PPPInterface(interface_id ID, driver_settings *settings,
PPPInterface *parent = NULL);
~PPPInterface();
void Delete();
status_t InitCheck() const;
interface_id ID() const
{ return fID; }
driver_settings* Settings()
{ return fSettings; }
@ -55,6 +59,12 @@ class PPPInterface {
struct ifq *InQueue() const
{ return fInQueue; }
// idle handling
bigtime_t IdleSince() const
{ return fIdleSince; }
bigtime_t DisconnectAfterIdleSince() const
{ return fDisconnectAfterIdleSince; }
void SetLinkMTU(uint32 linkMTU);
uint32 LinkMTU() const
{ return fLinkMTU; }
@ -142,6 +152,7 @@ class PPPInterface {
bool UnregisterInterface();
void CalculateMRU();
void CalculateBaudRate();
void Redial();
@ -150,7 +161,9 @@ class PPPInterface {
{ fParent = parent; }
private:
driver_parameter *fSettings;
interface_id fID;
// the manager assigns an ID to every interface
driver_settings *fSettings;
PPPStateMachine fStateMachine;
PPPLCP fLCP;
PPPReportManager fReportManager;
@ -164,6 +177,7 @@ class PPPInterface {
ppp_manager_info *fManager;
bigtime_t fIdleSince, fDisconnectAfterIdleSince;
uint32 fLinkMTU, fMRU, fHeaderLength;
PPPInterface *fParent;

View File

@ -41,10 +41,15 @@ class PPPLCP : public PPPProtocol {
{ return fOptionHandlers.CountItems(); }
PPPOptionHandler *OptionHandlerAt(int32 index) const;
PPPEncapsulator *Target() const
{ return fTarget; }
void SetTarget(PPPEncapsulator *target)
{ fTarget = target; }
// if target != all packtes will be passed to the encapsulator
// instead of the interface/device
uint32 AdditionalOverhead() const;
// the overhead caused by the target, the device, and the interface
private:
List<PPPOptionHandler*> fOptionHandlers;

View File

@ -13,25 +13,30 @@
#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 {
kernel_net_module_info knminfo;
// when you want to iterate through interfaces you should use locking
void (*lock)();
void (*unlock)();
uint32 (*create_interface)(driver_settings *settings, interface_id parent);
// you should always create interfaces using this function
void (*delete_interface)(interface_id ID);
// this marks the interface for deletion
ifnet* (*add_interface)(PPPInterface *interface);
bool (*remove_interface)(PPPInterface *interface);
ifnet* (*register_interface)(interface_id ID);
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);
void (*put_interface)(PPPInterface *interface);
void (*delete_interface)(PPPInterface *interface);
// this deletes the interface when it is not needed anymore
} ppp_manager;
status_t (*get_interfaces)(interface_id **interfaces, uint32 *count,
PPP_INTERFACE_FILTER filter = PPP_REGISTERED_INTERFACES);
// the user is responsible for free()'ing the interface_id array
} ppp_manager_info;
#endif

View File

@ -18,7 +18,7 @@ class PPPOptionHandler {
driver_parameter *settings);
virtual ~PPPOptionHandler();
virtual status_t InitCheck() = 0;
virtual status_t InitCheck() const;
void SetEnabled(bool enabled = true);
bool IsEnabled() const

View File

@ -18,7 +18,7 @@ class PPPProtocol {
driver_parameter *settings, int32 flags = PPP_NO_FLAGS);
virtual ~PPPProtocol();
virtual status_t InitCheck() const = 0;
virtual status_t InitCheck() const;
const char *Name() const
{ return fName; }
@ -41,7 +41,8 @@ class PPPProtocol {
bool IsEnabled() const
{ return fEnabled; }
void SetUpRequested(bool requested = true);
void SetUpRequested(bool requested = true)
{ fUpRequested = requested; }
bool IsUpRequested() const
{ return fUpRequested; }
@ -60,6 +61,8 @@ class PPPProtocol {
virtual status_t Send(mbuf *packet) = 0;
virtual status_t Receive(mbuf *packet) = 0;
virtual void Pulse();
protected:
void UpStarted();
@ -74,9 +77,10 @@ class PPPProtocol {
char *name;
PPP_PHASE fPhase;
uint16 fProtocol;
int32 fAddressFamily, fFlags;
int32 fAddressFamily;
PPPInterface fInterface;
driver_parameter fSettings;
int32 fFlags;
bool fEnabled;
bool fUpRequested;

View File

@ -26,7 +26,8 @@ enum PPP_REPORT_FLAGS {
enum PPP_REPORT_TYPE {
PPP_DESTRUCTION_REPORT = 0,
// 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)
@ -36,10 +37,13 @@ enum PPP_CONNECTION_REPORT_CODES {
PPP_REPORT_DOWN_SUCCESSFUL = 2,
PPP_REPORT_UP_ABORTED = 3,
PPP_REPORT_DEVICE_UP_FAILED = 4,
PPP_REPORT_AUTHENTICATION_FAILED = 5,
PPP_REPORT_CONNECTION_LOST = 6
PPP_REPORT_AUTHENTICATION_SUCCESSFUL = 5,
PPP_REPORT_PEER_AUTHENTICATION_SUCCESSFUL = 6,
PPP_REPORT_AUTHENTICATION_FAILED = 7,
PPP_REPORT_CONNECTION_LOST = 8
};
typedef struct ppp_report_packet {
int32 type;
int32 code;

View File

@ -6,3 +6,127 @@
//---------------------------------------------------------------------
#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();
}

View File

@ -6,3 +6,143 @@
//---------------------------------------------------------------------
#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);
}

View File

@ -12,7 +12,6 @@
#include "KPPPManager.h"
// general helper classes not only belonging to us
#include "AccessHelper.h"
#include "LockerHelper.h"
// tools only for us :)
@ -43,13 +42,15 @@ status_t redial_func(void *data);
status_t in_queue_thread(void *data);
PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NULL)
: fSettings(dup_driver_settings(settings)),
PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
PPPInterface *parent = NULL)
: fID(ID), fSettings(dup_driver_settings(settings)),
fStateMachine(*this), fLCP(*this), ReportManager()(StateMachine().Locker()),
fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0),
fDialRetriesLimit(0), fLinkMTU(1500), fAccessing(0), fChildrenCount(0),
fDevice(NULL), fFirstEncapsulator(NULL), fLock(StateMachine().Locker())
fDialRetriesLimit(0), fIdleSince(0), fLinkMTU(1500), fDevice(NULL),
fFirstEncapsulator(NULL), fLock(StateMachine().Locker())
{
// set up queue
fInQueue = start_ifq();
fInQueueThread = spawn_kernel_thread(in_queue_thread, "PPPInterface: Input",
B_NORMAL_PRIORITY, this);
@ -61,17 +62,32 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL
// are we a multilink subinterface?
if(parent && parent->IsMultilink()) {
fParent = parent;
fParent->AddChild(this);
fIsMultilink = true;
} else {
fParent = NULL;
fIsMultilink = false;
}
if(!fSettings)
if(!fSettings) {
fMode = PPP_CLIENT_MODE;
fDisconnectAfterIdleSince = 0;
return;
}
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);
if(!strcasecmp(value, PPP_SERVER_MODE_VALUE))
fMode = PPP_SERVER_MODE;
@ -132,7 +148,7 @@ PPPInterface::~PPPInterface()
void
PPPInterface::Delete()
{
fManager->delete_interface(this);
fManager->delete_interface(ID());
}
@ -177,7 +193,7 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
default:
return B_ERROR;
return B_ERROR;
}
return B_OK;
@ -206,11 +222,9 @@ PPPInterface::SetDevice(PPPDevice *device)
fDevice = device;
fLinkMTU = fDevice->MTU();
if(Ifnet())
Ifnet()->if_baudrate = max(fDevice->InputTransferRate(),
fDevice->OutputTransferRate());
CalculateMRU();
CalculateBaudRate();
}
@ -407,9 +421,7 @@ PPPInterface::RemoveChild(PPPInterface *child)
// parents cannot exist without their children
if(CountChildren() == 0 && fManager && Ifnet())
fManager->delete_interface(this);
CalculateMRU();
fManager->delete_interface(ID());
return true;
}
@ -534,7 +546,7 @@ PPPInterface::Up()
fUpThread = -1;
if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL)
fManager->delete_interface(this);
fManager->delete_interface(ID());
}
PPP_REPLY(sender, B_OK);
@ -572,7 +584,7 @@ PPPInterface::Up()
if(!DoesDialOnDemand()
&& report.code != PPP_REPORT_DOWN_SUCCESSFUL)
fManager->delete_interface(this);
fManager->delete_interface(ID());
PPP_REPLY(sender, B_OK);
ReportManager().DisableReports(PPP_CONNECTION_REPORT, me);
@ -599,12 +611,15 @@ PPPInterface::Up()
if(!DoesDialOnDemand()
&& report.code != PPP_REPORT_DOWN_SUCCESSFUL)
fManager->delete_interface(this);
fManager->delete_interface(ID());
return false;
}
}
}
// if the code is unknown we continue
PPP_REPLY(sender, B_OK);
}
return false;
@ -644,7 +659,7 @@ PPPInterface::Down()
}
if(!DoesDialOnDemand())
fManager->delete_interface(this);
fManager->delete_interface(ID());
return true;
}
@ -674,12 +689,11 @@ PPPInterface::LoadModules(const driver_settings *settings,
// multilink handling
for(int32 i = start;
i < settings->parameter_count && i < start + count;
i++) {
i < settings->parameter_count && i < start + count; i++) {
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],
parameters[i].parameters, PPP_MULTILINK_TYPE))
parameters[i].parameters, PPP_MULTILINK_TYPE))
return false;
break;
}
@ -690,14 +704,12 @@ PPPInterface::LoadModules(const driver_settings *settings,
if(IsMultilink() && !Parent()) {
// main interfaces only load the multilink module
// and create a child using their settings
AddChild(new PPPInterface(settings, this));
fManager->create_interface(settings, ID());
return true;
}
for(int32 i = start;
i < settings->parameter_count && i < start + count;
i++) {
i < settings->parameter_count && i < start + count; i++) {
type = -1;
name = settings->parameters[i].name;
@ -715,9 +727,9 @@ PPPInterface::LoadModules(const driver_settings *settings,
if(type >= 0)
for(int32 value_id = 0; value_id < settings->parameters[i].value_count;
value_id++)
value_id++)
if(!LoadModule(settings->parameters[i].value[value_id],
settings->parameters[i].parameters, type))
settings->parameters[i].parameters, type))
return false;
}
@ -756,8 +768,6 @@ PPPInterface::LoadModule(const char *name, const driver_parameter *parameter,
status_t
PPPInterface::Send(mbuf *packet, uint16 protocol)
{
AccessHelper access(&fAccessing);
if(!packet)
return B_ERROR;
@ -781,8 +791,10 @@ PPPInterface::Send(mbuf *packet, uint16 protocol)
// Note that these protocols are not passed to encapsulators!
PPPProtocol *sending_protocol = ProtocolFor(protocol);
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);
}
// never send normal protocols when we are down
if(!IsUp()) {
@ -790,6 +802,8 @@ PPPInterface::Send(mbuf *packet, uint16 protocol)
return B_ERROR;
}
fIdleSince = system_time();
// send to next up encapsulator
if(!fFirstEncapsulator)
return SendToDevice(packet, protocol);
@ -804,8 +818,6 @@ PPPInterface::Send(mbuf *packet, uint16 protocol)
status_t
PPPInterface::Receive(mbuf *packet, uint16 protocol)
{
AccessHelper access(&fAccessing);
if(!packet)
return B_ERROR;
@ -874,8 +886,6 @@ PPPInterface::Receive(mbuf *packet, uint16 protocol)
status_t
PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
{
AccessHelper access(&fAccessing);
if(!packet)
return B_ERROR;
@ -914,7 +924,7 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
}
// encode in ppp frame
packet = M_PREPEND(packet, sizeof(uint16));
M_PREPEND(packet, sizeof(uint16));
if(packet == NULL)
return B_ERROR;
@ -924,11 +934,13 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
uint16 *header = mtod(packet, uint16*);
*header = protocol;
fIdleSince = system_time();
// 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()) {
if((packet->m_flags & M_PKTHDR && packet->m_pkthdr.len > LinkMTU())
|| packet->m_len > LinkMTU()) {
m_freem(packet);
return B_ERROR;
}
@ -945,8 +957,6 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
status_t
PPPInterface::ReceiveFromDevice(mbuf *packet)
{
AccessHelper access(&fAccessing);
if(!packet)
return B_ERROR;
@ -961,16 +971,12 @@ PPPInterface::ReceiveFromDevice(mbuf *packet)
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();
// make sure the protocols think we received
// the packet
if(!packet->m_pkthdr.rcvif) {
m_freem(packet);
return B_ERROR;
}
}
return Receive(packet, protocol);
}
@ -979,10 +985,24 @@ PPPInterface::ReceiveFromDevice(mbuf *packet)
void
PPPInterface::Pulse()
{
// TODO:
// check our idle time
// check our idle time and disconnect if needed
if(fDisconnectAfterIdleSince > 0 && fIdleSince != 0
&& fIdleSince - system_time() >= fDisconnectAfterIdleSince) {
StateMachine().CloseEvent();
return;
}
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)
return false;
fIfnet = fManager->add_interface(this);
fIfnet = fManager->register_interface(ID());
if(!fIfnet)
return false;
if(Device())
fIfnet->if_baudrate = max(Device()->InputTransferRate(),
Device()->OutputTransferRate());
CalculateBaudRate();
return true;
}
@ -1031,7 +1049,7 @@ PPPInterface::UnregisterInterface()
if(!fManager)
return false;
fManager->remove_interface(this);
fManager->unregister_interface(ID());
fIfnet = NULL;
return true;
@ -1047,10 +1065,8 @@ PPPInterface::CalculateMRU()
fHeaderLength = sizeof(uint16);
PPPEncapsulator encapsulator = fFirstEncapsulator;
while(encapsulator) {
for(; encapsulator; encapsulator = encapsulator->Next())
fHeaderLength += encapsulator->Overhead();
encapsulator = encapsulator->Next();
}
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
PPPInterface::Redial()
{

View File

@ -64,3 +64,16 @@ PPPLCP::OptionHandlerAt(int32 index) const
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;
}

View File

@ -6,3 +6,33 @@
//---------------------------------------------------------------------
#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;
}

View File

@ -6,3 +6,129 @@
//---------------------------------------------------------------------
#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);
}

View File

@ -105,6 +105,8 @@ PPPStateMachine::AuthenticationAccepted(const char *name)
fAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL;
free(fAuthenticationName);
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;
free(fPeerAuthenticationName);
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);
if(Phase() <= PPP_TERMINATION_PHASE || State() != PPP_STARTING_STATE) {
if(Phase() <= PPP_TERMINATION_PHASE) {
interface->StateMachine().CloseEvent();
return;
}
NewState(PPP_OPENED_STATE);
Interface()->CalculateBaudRate();
if(Phase() == PPP_ESTABLISHMENT_PHASE) {
NewPhase(PPP_AUTHENTICATION_PHASE);
// this is the first interface that went up
Interface()->SetLinkMTU(interface->LinkMTU());
locker.UnlockNow();
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);
uint32 linkMTU = 0;
// the new linkMTU
Interface()->CalculateBaudRate();
// when all children are down we should not be running
if(Interface()->IsMultilink() && !Interface()->Parent()) {
uint32 count = 0;
@ -209,10 +225,19 @@ PPPStateMachine::DownEvent(PPPInterface *interface)
for(int32 index = 0; index < Interface()->CountChildren(); 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;
}
}
Interface()->SetLinkMTU(linkMTU);
if(count == 0) {
locker.UnlockNow();
DownEvent();
@ -372,10 +397,7 @@ PPPStateMachine::UpEvent()
return;
// it is not our device that went up...
if(Interface()->Ifnet())
Interface()->Ifnet()->if_baudrate = max(
Interface()->Device()->InputTransferRate(),
Interface()->Device()->OutputTransferRate());
Interface()->CalculateBaudRate();
switch(State()) {
case PPP_INITIAL_STATE:
@ -428,14 +450,14 @@ PPPStateMachine::DownEvent()
{
LockerHelper locker(fLock);
if(!Interface()->Device() || Interface()->Device->IsUp())
if(Interface()->Device() && Interface()->Device->IsUp())
return;
// it is not our device that went up...
if(Interface()->Ifnet())
Interface()->Ifnet()->if_baudrate = max(
Interface()->Device()->InputTransferRate(),
Interface()->Device()->OutputTransferRate());
Interface()->CalculateBaudRate();
// reset IdleSince
Interface()->fIdleSince = 0;
switch(State()) {
case PPP_CLOSED_STATE:
@ -1150,7 +1172,7 @@ PPPStateMachine::RCREvent(mbuf *packet)
handled = false;
for(int32 index = 0; index < LCP().CountOptionHandlers();
index++) {
index++) {
handler = LCP().OptionHandlerAt(index);
error = handler->ParseRequest(&request, item, &nak, &reject);
if(error == PPP_UNHANLED)
@ -1171,9 +1193,9 @@ PPPStateMachine::RCREvent(mbuf *packet)
}
if(nak.CountItems() > 0)
RCRBadEvent(nak.ToMbuf(), NULL);
RCRBadEvent(nak.ToMbuf(LCP().AdditionalOverhead()), NULL);
else if(reject.CountItmes() > 0)
RCRBadEvent(NULL, reject.ToMbuf());
RCRBadEvent(NULL, reject.ToMbuf(LCP().AdditionalOverhead()));
else
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;
// reserve some space for other protocols
m->m_data += PPP_PROTOCOL_OVERHEAD;
if(LCP().Encapsulator())
m->m_data += LCP().Encapsulator()->Overhead();
if(Interface()->Device())
m->m_data += Interface()->Device()->Overhead();
m->m_data += LCP().AdditionalOverhead();
lcp_packet *request = mtod(m, lcp_packet*);
request->code = PPP_TERMINATE_REQUEST;
@ -1398,8 +1416,36 @@ PPPStateMachine::SendTerminateAck(mbuf *request)
void
PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol, uint8 type)
{
// TODO:
// add the packet to the reject and truncate it if needed
int32 length;
// 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()
{
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;
encapsulator_handler = encapsulator_handler->Next())
encapsualtor_handler->Down();
if(encapsulator_handler->IsEnabled())
encapsualtor_handler->Down();
}