Replaced some pointers with references.

Added support for Protocol-Field-Compression including the needed handler.
Added initial support for ppp_manager's ioctl() function (currently, PPPInterface does not handle any ioctls). These calls are routed to all handlers, too (if PPPInterface did not handle the ioctl).
Changed naming of local states and report codes (authentication, etc.). These now have "Local"/"LOCAL" in their name.
Some minor changes.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4672 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald 2003-09-13 17:57:12 +00:00
parent 6151971100
commit 7ff713dadd
23 changed files with 630 additions and 168 deletions

View File

@ -1,3 +1,10 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
//---------------------------------------------------------------------
#ifndef _K_PPP__H
#define _K_PPP__H

View File

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

View File

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

View File

@ -141,6 +141,21 @@ class PPPInterface {
ppp_phase Phase() const
{ return fStateMachine.Phase(); }
// Protocol-Field-Compression
bool SetPFCOptions(uint8 pfcOptions);
uint8 PFCOptions() const
{ return fPFCOptions; }
ppp_pfc_state LocalPFCState() const
{ return fLocalPFCState; }
// the local PFC state says if we accepted a request from the peer
// i.e.: we may use PFC in outgoing packets
ppp_pfc_state PeerPFCState() const
{ return fPeerPFCState; }
// the peer PFC state says if the peer accepted a request us
// i.e.: the peer might send PFC-compressed packets to us
bool UseLocalPFC() const
{ return LocalPFCState() & PPP_PFC_ACCEPTED; }
bool Up();
// in server mode Up() listens for an incoming connection
bool Down();
@ -175,6 +190,11 @@ class PPPInterface {
// saves the returned ifnet structure
bool UnregisterInterface();
status_t StackControl(uint32 op, void *data);
// stack routes ioctls to interface
status_t ControlEachHandler(uint32 op, void *data, size_t length);
// this calls Control() with the given parameters for each handler
void CalculateInterfaceMTU();
void CalculateBaudRate();
@ -213,9 +233,9 @@ class PPPInterface {
bool fAutoRedial, fDialOnDemand;
vint32 fAccesing;
ppp_mode fMode;
ppp_pfc_state fLocalPFCState, fPeerPFCState;
uint8 fPFCOptions;
PPPDevice *fDevice;
PPPEncapsulator *fFirstEncapsulator;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -62,6 +62,25 @@ enum {
// could not send a packet because device is not connected
};
// PFC options
enum {
PPP_REQUEST_PFC = 0x01,
// try to request PFC (does not fail if not successful)
PPP_ALLOW_PFC = 0x02,
// allow PFC if other side requests it
PPP_FORCE_PFC_REQUEST = 0x04,
// if PFC request fails the connection attempt will terminate
PPP_FREEZE_PFC_OPTIONS = 0x80
// the options cannot be changed if this flag is set (mainly used by PPPDevice)
};
enum ppp_pfc_state {
PPP_PFC_DISABLED,
PPP_PFC_ACCEPTED,
PPP_PFC_REJECTED
// not used for peer state
};
// protocol and encapsulator flags
enum {
PPP_NO_FLAGS = 0x00,
@ -100,7 +119,8 @@ enum ppp_phase {
// this defines the order in which the packets get encapsulated
enum ppp_encapsulation_level {
PPP_MULTILINK_LEVEL = 0,
PPP_DEVICE_LEVEL = 0,
PPP_MULTILINK_LEVEL = 2,
PPP_ENCRYPTION_LEVEL = 5,
PPP_COMPRESSION_LEVEL = 10
};

View File

@ -41,10 +41,11 @@ enum ppp_connection_report_codes {
PPP_REPORT_DOWN_SUCCESSFUL = 2,
PPP_REPORT_UP_ABORTED = 3,
PPP_REPORT_DEVICE_UP_FAILED = 4,
PPP_REPORT_AUTHENTICATION_SUCCESSFUL = 5,
PPP_REPORT_LOCAL_AUTHENTICATION_SUCCESSFUL = 5,
PPP_REPORT_PEER_AUTHENTICATION_SUCCESSFUL = 6,
PPP_REPORT_AUTHENTICATION_FAILED = 7,
PPP_REPORT_CONNECTION_LOST = 8
PPP_REPORT_LOCAL_AUTHENTICATION_FAILED = 7,
PPP_REPORT_PEER_AUTHENTICATION_FAILED = 8,
PPP_REPORT_CONNECTION_LOST = 9
};

View File

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

View File

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

View File

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

View File

@ -19,6 +19,7 @@
#include <PPPControl.h>
#include <KPPPDevice.h>
#include <KPPPEncapsulator.h>
#include <KPPPLCPExtension.h>
#include <KPPPOptionHandler.h>
#include <KPPPModule.h>
#include <KPPPManager.h>
@ -30,6 +31,9 @@
// tools only for us :)
#include "settings_tools.h"
// internal modules
#include "_KPPPPFCHandler.h"
// TODO:
// - implement timers with support for settings next time instead of receiving timer
@ -52,13 +56,36 @@ status_t interface_deleter_thread(void *data);
PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
PPPInterface *parent = NULL)
: fID(ID), fSettings(dup_driver_settings(settings)),
fStateMachine(*this), fLCP(*this), fReportManager(StateMachine().Locker()),
fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0),
fDialRetriesLimit(0), fIdleSince(0), fMRU(1500), fInterfaceMTU(1498),
fHeaderLength(2), fAutoRedial(false), fDialOnDemand(false), fDevice(NULL),
fFirstEncapsulator(NULL), fLock(StateMachine().Locker()), fDeleteCounter(0)
: fID(ID),
fSettings(dup_driver_settings(settings)),
fStateMachine(*this),
fLCP(*this),
fReportManager(StateMachine().Locker()),
fIfnet(NULL),
fUpThread(-1),
fRedialThread(-1),
fDialRetry(0),
fDialRetriesLimit(0),
fIdleSince(0),
fMRU(1500),
fInterfaceMTU(1498),
fHeaderLength(2),
fAutoRedial(false),
fDialOnDemand(false),
fLocalPFCState(PPP_PFC_DISABLED),
fPeerPFCState(PPP_PFC_DISABLED),
fPFCOptions(0),
fDevice(NULL),
fFirstEncapsulator(NULL),
fLock(StateMachine().Locker()),
fDeleteCounter(0)
{
// add internal modules
_PPPPFCHandler *pfcHandler =
new _PPPPFCHandler(fLocalPFCState, fPeerPFCState, *this);
if(pfcHandler->InitCheck() != B_OK)
delete pfcHandler;
// set up dial delays
fDialRetryDelay = 3000;
// 3s delay between each new attempt to redial
@ -253,9 +280,13 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
info->mode = Mode();
info->state = State();
info->phase = Phase();
info->authenticationStatus = StateMachine().AuthenticationStatus();
info->localAuthenticationStatus =
StateMachine().LocalAuthenticationStatus();
info->peerAuthenticationStatus =
StateMachine().PeerAuthenticationStatus();
info->localPFCState = LocalPFCState();
info->peerPFCState = PeerPFCState();
info->pfcOptions = PFCOptions();
info->protocolsCount = CountProtocols();
info->encapsulatorsCount = CountEncapsulators();
info->optionHandlersCount = LCP().CountOptionHandlers();
@ -263,6 +294,10 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
info->childrenCount = CountChildren();
info->MRU = MRU();
info->interfaceMTU = InterfaceMTU();
info->dialRetry = fDialRetry;
info->dialRetriesLimit = fDialRetriesLimit;
info->dialRetryDelay = DialRetryDelay();
info->redialDelay = RedialDelay();
info->idleSince = IdleSince();
info->disconnectAfterIdleSince = DisconnectAfterIdleSince();
info->doesDialOnDemand = DoesDialOnDemand();
@ -361,7 +396,16 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
} break;
case PPPC_CONTROL_LCP_EXTENSION: {
return PPP_UNHANDLED;
if(length < sizeof(ppp_control_info) || !data)
return B_ERROR;
ppp_control_info *control = (ppp_control_info*) data;
PPPLCPExtension *extension_handler = LCP().LCPExtensionAt(control->index);
if(!extension_handler)
return B_BAD_INDEX;
return extension_handler->Control(control->op, control->data,
control->length);
} break;
case PPPC_CONTROL_CHILD: {
@ -376,8 +420,19 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
return child->Control(control->op, control->data, control->length);
} 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 PPP_UNHANDLED;
return B_BAD_VALUE;
}
return B_OK;
@ -718,6 +773,17 @@ PPPInterface::SetDialOnDemand(bool dialondemand = true)
}
bool
PPPInterface::SetPFCOptions(uint8 pfcOptions)
{
if(PFCOptions() & PPP_FREEZE_PFC_OPTIONS)
return false;
fPFCOptions = pfcOptions;
return true;
}
bool
PPPInterface::Up()
{
@ -742,9 +808,13 @@ PPPInterface::Up()
fLock.Unlock();
// fUpThread tells the state machine to go up
if(me == fUpThread)
if(me == fUpThread || me == fRedialThread)
StateMachine().OpenEvent();
if(me == fRedialThread && me != fUpThread)
return true;
// the redial thread is doing a DialRetry in this case
while(true) {
if(IsUp()) {
// lock needs timeout because destructor could have locked the interface
@ -763,6 +833,9 @@ PPPInterface::Up()
return true;
}
// A wrong code usually happens when the redial thread gets notified
// of a Down() request. In that case a report will follow soon, so
// this can be ignored.
if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE)
continue;
@ -798,6 +871,8 @@ PPPInterface::Up()
if(me == fUpThread) {
fDialRetry = 0;
fUpThread = -1;
send_data_with_timeout(fRedialThread, 0, NULL, 0, 200);
// notify redial thread that we do not need it anymore
}
PPP_REPLY(sender, B_OK);
@ -805,7 +880,8 @@ PPPInterface::Up()
return true;
} else if(report.code == PPP_REPORT_DOWN_SUCCESSFUL
|| report.code == PPP_REPORT_UP_ABORTED
|| report.code == PPP_REPORT_AUTHENTICATION_FAILED) {
|| report.code == PPP_REPORT_LOCAL_AUTHENTICATION_FAILED
|| report.code == PPP_REPORT_PEER_AUTHENTICATION_FAILED) {
if(me == fUpThread) {
fDialRetry = 0;
fUpThread = -1;
@ -857,7 +933,7 @@ PPPInterface::Up()
} else {
++fDialRetry;
PPP_REPLY(sender, B_OK);
StateMachine().OpenEvent();
Redial(DialRetryDelay());
continue;
}
} else if(report.code == PPP_REPORT_CONNECTION_LOST) {
@ -866,7 +942,7 @@ PPPInterface::Up()
if(DoesAutoRedial() && fDialRetry < fDialRetriesLimit) {
++fDialRetry;
PPP_REPLY(sender, B_OK);
StateMachine().OpenEvent();
Redial(DialRetryDelay());
continue;
} else {
fDialRetry = 0;
@ -897,6 +973,9 @@ PPPInterface::Down()
if(InitCheck() != B_OK)
return false;
send_data_with_timeout(fRedialThread, 0, NULL, 0, 200);
// the redial thread should be notified that the user wants to disconnect
// this locked section guarantees that there are no state changes before we
// enable the connection reports
LockerHelper locker(fLock);
@ -1218,16 +1297,26 @@ PPPInterface::SendToDevice(struct mbuf *packet, uint16 protocol)
return B_ERROR;
}
// encode in ppp frame
M_PREPEND(packet, 2);
// encode in ppp frame and consider using PFC
if(UseLocalPFC() && protocol & 0xFF00 == 0) {
M_PREPEND(packet, 1);
if(packet == NULL)
return B_ERROR;
if(packet == NULL)
return B_ERROR;
// set protocol (the only header field)
protocol = htons(protocol);
uint16 *header = mtod(packet, uint16*);
*header = protocol;
uint8 *header = mtod(packet, uint8*);
*header = protocol & 0xFF;
} else {
M_PREPEND(packet, 2);
if(packet == NULL)
return B_ERROR;
// set protocol (the only header field)
protocol = htons(protocol);
uint16 *header = mtod(packet, uint16*);
*header = protocol;
}
fIdleSince = real_time_clock();
@ -1260,13 +1349,16 @@ PPPInterface::ReceiveFromDevice(struct mbuf *packet)
return B_ERROR;
}
// decode ppp frame
uint16 *protocol = mtod(packet, uint16*);
*protocol = ntohs(*protocol);
// decode ppp frame and recognize PFC
uint16 protocol = *mtod(packet, uint8*);
if(protocol == 0)
m_adj(packet, 1);
else {
protocol = ntohs(*mtod(packet, uint16*));
m_adj(packet, 2);
}
m_adj(packet, 2);
return Receive(packet, *protocol);
return Receive(packet, protocol);
}
@ -1351,6 +1443,89 @@ PPPInterface::UnregisterInterface()
}
// stack routes ioctls to interface
status_t
PPPInterface::StackControl(uint32 op, void *data)
{
// TODO:
// implement when writing ppp_manager module
switch(op) {
default:
return B_BAD_VALUE;
}
return B_OK;
}
// This calls Control() with the given parameters for each handler.
// Return values:
// B_OK: all handlers returned B_OK
// B_BAD_VALUE: no handler was found
// any other value: the error value that was returned by the last handler that failed
status_t
PPPInterface::ControlEachHandler(uint32 op, void *data, size_t length)
{
int32 index;
status_t result = B_BAD_VALUE, tmp;
// protocols
PPPProtocol *protocol;
for(index = 0; index < CountProtocols(); index++) {
protocol = ProtocolAt(index);
if(!protocol)
break;
tmp = protocol->Control(op, data, length);
if(tmp == B_OK && result == B_BAD_VALUE)
result = B_OK;
else if(tmp != B_BAD_VALUE)
result = tmp;
}
// encapsulators
PPPEncapsulator *encapsulator = FirstEncapsulator();
for(; encapsulator; encapsulator = encapsulator->Next()) {
tmp = encapsulator->Control(op, data, length);
if(tmp == B_OK && result == B_BAD_VALUE)
result = B_OK;
else if(tmp != B_BAD_VALUE)
result = tmp;
}
// option handlers
PPPOptionHandler *optionHandler;
for(index = 0; index < LCP().CountOptionHandlers(); index++) {
optionHandler = LCP().OptionHandlerAt(index);
if(!optionHandler)
break;
tmp = optionHandler->Control(op, data, length);
if(tmp == B_OK && result == B_BAD_VALUE)
result = B_OK;
else if(tmp != B_BAD_VALUE)
result = tmp;
}
// LCP extensions
PPPLCPExtension *lcpExtension;
for(index = 0; index < LCP().CountLCPExtensions(); index++) {
lcpExtension = LCP().LCPExtensionAt(index);
if(!lcpExtension)
break;
tmp = lcpExtension->Control(op, data, length);
if(tmp == B_OK && result == B_BAD_VALUE)
result = B_OK;
else if(tmp != B_BAD_VALUE)
result = tmp;
}
return result;
}
void
PPPInterface::CalculateInterfaceMTU()
{
@ -1446,8 +1621,11 @@ redial_thread(void *data)
receive_data(&sender, &info, sizeof(redial_info));
// we try to receive data instead of snooze, so we can quit on destruction
if(receive_data_with_timeout(&sender, &code, NULL, 0, info.delay) == B_OK)
if(receive_data_with_timeout(&sender, &code, NULL, 0, info.delay) == B_OK) {
*info.thread = -1;
info.interface->Report(PPP_CONNECTION_REPORT, PPP_REPORT_UP_ABORTED, NULL, 0);
return B_OK;
}
info.interface->Up();
*info.thread = -1;

View File

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

View File

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

View File

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

View File

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

View File

@ -93,7 +93,7 @@ PPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 len
LockerHelper locker(fLock);
status_t result;
thread_id sender;
thread_id sender, me = find_thread(NULL);
bool acceptable = true;
ppp_report_packet report;
@ -107,6 +107,10 @@ PPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 len
for(int32 index = 0; index < fReportRequests.CountItems(); index++) {
request = fReportRequests.ItemAt(index);
// do not send to yourself
if(request->thread == me)
continue;
result = send_data_with_timeout(request->thread, PPP_REPORT_CODE, &report,
sizeof(report), PPP_REPORT_TIMEOUT);

View File

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

View File

@ -0,0 +1,120 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
//---------------------------------------------------------------------
#include "_KPPPPFCHandler.h"
#include <KPPPConfigurePacket.h>
#define PFC_TYPE 0x7
_PPPPFCHandler::_PPPPFCHandler(ppp_pfc_state& localPFCState,
ppp_pfc_state& peerPFCState, PPPInterface& interface)
: PPPOptionHandler("PFC Handler", PFC_TYPE, interface, NULL),
fLocalPFCState(localPFCState),
fPeerPFCState(peerPFCState)
{
}
status_t
_PPPPFCHandler::AddToRequest(PPPConfigurePacket& request)
{
// is PFC not requested or was it rejected?
if(fLocalPFCState & PPP_PFC_REJECTED
|| (Interface().PFCOptions() & PPP_REQUEST_PFC) == 0)
return B_OK;
// add PFC request
ppp_configure_item item;
item.type = PFC_TYPE;
item.length = 2;
return request.AddItem(&item) ? B_OK : B_ERROR;
}
status_t
_PPPPFCHandler::ParseNak(const PPPConfigurePacket& nak)
{
// naks do not contain PFC items
if(nak.ItemWithType(PFC_TYPE))
return B_ERROR;
return B_OK;
}
status_t
_PPPPFCHandler::ParseReject(const PPPConfigurePacket& reject)
{
if(reject.ItemWithType(PFC_TYPE)) {
fLocalPFCState = PPP_PFC_REJECTED;
if(Interface().PFCOptions() & PPP_FORCE_PFC_REQUEST)
return B_ERROR;
}
return B_OK;
}
status_t
_PPPPFCHandler::ParseAck(const PPPConfigurePacket& ack)
{
if(ack.ItemWithType(PFC_TYPE))
fLocalPFCState = PPP_PFC_ACCEPTED;
else {
fLocalPFCState = PPP_PFC_DISABLED;
if(Interface().PFCOptions() & PPP_FORCE_PFC_REQUEST)
return B_ERROR;
}
return B_OK;
}
status_t
_PPPPFCHandler::ParseRequest(const PPPConfigurePacket& request,
int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject)
{
if(!request.ItemWithType(PFC_TYPE))
return B_OK;
if((Interface().PFCOptions() & PPP_ALLOW_PFC) == 0) {
ppp_configure_item item;
item.type = PFC_TYPE;
item.length = 2;
return reject.AddItem(&item) ? B_OK : B_ERROR;
}
return B_OK;
}
status_t
_PPPPFCHandler::SendingAck(const PPPConfigurePacket& ack)
{
ppp_configure_item *item = ack.ItemWithType(PFC_TYPE);
if(item && (Interface().PFCOptions() & PPP_ALLOW_PFC) == 0)
return B_ERROR;
if(item)
fPeerPFCState = PPP_PFC_ACCEPTED;
else
fPeerPFCState = PPP_PFC_DISABLED;
return B_OK;
}
void
_PPPPFCHandler::Reset()
{
fLocalPFCState = fPeerPFCState = PPP_PFC_DISABLED;
}

View File

@ -0,0 +1,35 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
//---------------------------------------------------------------------
#ifndef __K_PPP_PFC_HANDLER__H
#define __K_PPP_PFC_HANDLER__H
#include <KPPPOptionHandler.h>
class _PPPPFCHandler : public PPPOptionHandler {
public:
_PPPPFCHandler(ppp_pfc_state& localPFCState, ppp_pfc_state& peerPFCState,
PPPInterface& interface);
virtual status_t AddToRequest(PPPConfigurePacket& request);
virtual status_t ParseNak(const PPPConfigurePacket& nak);
virtual status_t ParseReject(const PPPConfigurePacket& reject);
virtual status_t ParseAck(const PPPConfigurePacket& ack);
virtual status_t ParseRequest(const PPPConfigurePacket& request,
int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject);
virtual status_t SendingAck(const PPPConfigurePacket& ack);
virtual void Reset();
private:
ppp_pfc_state &fLocalPFCState, &fPeerPFCState;
};
#endif