Added PPPLCPExtension (allows additional codes for LCP).

Added Control() op codes for report enabling/disabling.
Fixed memory leaks in StateMachine and LCP (packets were not freed).
Some minor changes.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4514 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald 2003-09-06 17:13:51 +00:00
parent a602502a7e
commit b8561cdd29
20 changed files with 379 additions and 110 deletions

View File

@ -49,9 +49,9 @@ enum PPP_EVENT {
PPP_RXR_EVENT
};
// LCP protocol types as defined in RFC 1661
// LCP protocol codes as defined in RFC 1661
// ToDo: add LCP extensions
enum PPP_LCP_TYPE {
enum PPP_LCP_CODE {
PPP_CONFIGURE_REQUEST = 1,
PPP_CONFIGURE_ACK = 2,
PPP_CONFIGURE_NAK = 3,

View File

@ -8,8 +8,6 @@
#ifndef _K_PPP_DEVICE__H
#define _K_PPP_DEVICE__H
#include <driver_settings.h>
#include <KPPPDefs.h>
#ifndef _K_PPP_INTERFACE__H
@ -78,14 +76,13 @@ class PPPDevice {
void DownEvent();
protected:
uint32 fMTU;
bool fIsUp;
private:
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
PPPInterface& fInterface;
driver_parameter *fSettings;
uint32 fMTU;
};

View File

@ -8,12 +8,8 @@
#ifndef _K_PPP_ENCAPSULATOR__H
#define _K_PPP_ENCAPSULATOR__H
#include <driver_settings.h>
#include <KPPPDefs.h>
class PPPInterface;
#ifndef _K_PPP_INTERFACE__H
#include <KPPPInterface.h>
#endif

View File

@ -23,6 +23,7 @@
#endif
class PPPEncapsulator;
class PPPLCPExtension;
class PPPOptionHandler;
@ -30,7 +31,7 @@ typedef struct ppp_lcp_packet {
uint8 code;
uint8 id;
uint16 length;
int8 data[0];
uint8 data[0];
} ppp_lcp_packet;
@ -56,6 +57,12 @@ class PPPLCP : public PPPProtocol {
{ return fOptionHandlers.CountItems(); }
PPPOptionHandler *OptionHandlerAt(int32 index) const;
bool AddLCPExtension(PPPLCPExtension *extension);
bool RemoveLCPExtension(PPPLCPExtension *extension);
int32 CountLCPExtensions() const
{ return fLCPExtensions.CountItems(); }
PPPLCPExtension *LCPExtensionAt(int32 index) const;
PPPEncapsulator *Target() const
{ return fTarget; }
void SetTarget(PPPEncapsulator *target)
@ -78,6 +85,7 @@ class PPPLCP : public PPPProtocol {
PPPStateMachine& fStateMachine;
List<PPPOptionHandler*> fOptionHandlers;
List<PPPLCPExtension*> fLCPExtensions;
PPPEncapsulator *fTarget;
};

View File

@ -0,0 +1,60 @@
//----------------------------------------------------------------------
// 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_LCP_EXTENSION__H
#define __K_PPP_LCP_EXTENSION__H
#include <KPPPDefs.h>
#ifndef _K_PPP_INTERFACE__H
#include <KPPPInterface.h>
#endif
class PPPLCPExtension {
public:
PPPLCPExtension(const char *name, uint8 code, PPPInterface& interface,
driver_parameter *settings);
virtual ~PPPLCPExtension();
virtual status_t InitCheck() const;
const char *Name() const
{ return fName; }
PPPInterface& Interface() const
{ return fInterface; }
driver_parameter *Settings() const
{ return fSettings; }
void SetEnabled(bool enabled = true)
{ fEnabled = enabled; }
bool IsEnabled() const
{ return fEnabled; }
uint8 Code() const
{ return fCode; }
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 Pulse();
private:
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
PPPInterface& fInterface;
driver_parameter *fSettings;
uint8 fCode;
bool fEnabled;
};
#endif

View File

@ -8,8 +8,6 @@
#ifndef _K_PPP_OPTION_HANDLER__H
#define _K_PPP_OPTION_HANDLER__H
#include <driver_settings.h>
#include <KPPPDefs.h>
#ifndef _K_PPP_INTERFACE__H
@ -35,7 +33,8 @@ class PPPOptionHandler {
driver_parameter *Settings() const
{ return fSettings; }
void SetEnabled(bool enabled = true);
void SetEnabled(bool enabled = true)
{ fEnabled = enabled; }
bool IsEnabled() const
{ return fEnabled; }

View File

@ -1,21 +0,0 @@
//----------------------------------------------------------------------
// 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_REPORT_DEFS__H
#define _K_PPP_REPORT_DEFS__H
#include <PPPReportDefs.h>
typedef struct ppp_report_request {
thread_id thread;
int32 type;
int32 flags;
} ppp_report_request;
#endif

View File

@ -10,7 +10,8 @@
#include <OS.h>
#include <KPPPReportDefs.h>
#include <KPPPDefs.h>
#include <PPPReportDefs.h>
#include <List.h>
@ -23,7 +24,7 @@ class PPPReportManager {
~PPPReportManager();
void EnableReports(PPP_REPORT_TYPE type, thread_id thread,
int32 flags = PPP_NO_REPORT_FLAGS);
int32 flags = PPP_NO_FLAGS);
void DisableReports(PPP_REPORT_TYPE type, thread_id thread);
bool DoesReport(PPP_REPORT_TYPE type, thread_id thread);
bool Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length);

View File

@ -11,7 +11,6 @@
#include <KPPPDefs.h>
class PPPEncapsulator;
class PPPInterface;
class PPPProtocol;
#ifndef _K_PPP_INTERFACE__H
@ -106,7 +105,8 @@ class PPPStateMachine {
void RCNEvent(struct mbuf *packet);
void RTREvent(struct mbuf *packet);
void RTAEvent(struct mbuf *packet);
void RUCEvent(struct mbuf *packet, uint16 protocol, uint8 type = PPP_PROTOCOL_REJECT);
void RUCEvent(struct mbuf *packet, uint16 protocol,
uint8 code = PPP_PROTOCOL_REJECT);
void RXJGoodEvent(struct mbuf *packet);
void RXJBadEvent(struct mbuf *packet);
void RXREvent(struct mbuf *packet);
@ -128,8 +128,8 @@ class PPPStateMachine {
void SendConfigureAck(struct mbuf *packet);
void SendConfigureNak(struct mbuf *packet);
void SendTerminateRequest();
void SendTerminateAck(struct mbuf *request);
void SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type);
void SendTerminateAck(struct mbuf *request = NULL);
void SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 code);
void SendEchoReply(struct mbuf *request);
void BringHandlersUp();

View File

@ -22,7 +22,6 @@
#define PPP_OPTION_HANDLER_OPS_START PPP_OPS_START + 5 * PPP_RESERVE_OPS_COUNT
#define PPP_LCP_EXTENSION_OPS_START PPP_OPS_START + 6 * PPP_RESERVE_OPS_COUNT
#define PPP_COMMON_OPS_START PPP_OPS_START + 10 * PPP_RESERVE_OPS_COUNT
#define PPP_COMMON_PROTO_ENCAPS_OPS_START PPP_OPS_START + 11 * PPP_RESERVE_OPS_COUNT
#define PPP_USER_OPS_START PPP_OPS_START + 32 * PPP_RESERVE_OPS_COUNT
@ -34,6 +33,11 @@ enum PPP_CONTROL_OPS {
PPPC_SET_DIAL_ON_DEMAND,
PPPC_SET_AUTO_REDIAL,
// these control ops use the ppp_report_request structure
PPPC_ENABLE_INTERFACE_REPORTS,
PPPC_DISABLE_INTERFACE_REPORTS,
// flags are not used for this control op
// handler access
PPPC_CONTROL_DEVICE,
PPPC_CONTROL_PROTOCOL,
@ -49,31 +53,13 @@ enum PPP_CONTROL_OPS {
PPPC_SET_MTU,
// -----------------------------------------------------
// -----------------------------------------------------
// PPPProtocol
// -----------------------------------------------------
// -----------------------------------------------------
// PPPEncapsulator
// -----------------------------------------------------
// -----------------------------------------------------
// PPPOptionHandler
PPPC_GET_OPTION_HANDLER_INFO = PPP_OPTION_HANDLER_OPS_START,
// -----------------------------------------------------
// -----------------------------------------------------
// PPPLCPExtension
// -----------------------------------------------------
// -----------------------------------------------------
// Common/mixed ops
PPPC_GET_HANDLER_INFO = PPP_COMMON_OPS_START,
// PPPProtocol and PPPEncapsulator
PPPC_SET_ENABLED,
// -----------------------------------------------------
// -----------------------------------------------------
// PPPProtocol and PPPEncapsulator
PPPC_GET_SIMPLE_HANDLER_INFO,
// PPPOptionHandler and PPPLCPExtension
// -----------------------------------------------------
PPP_CONTROL_OPS_END = B_DEVICE_OP_CODES_END + 0xFFFF
@ -166,17 +152,19 @@ typedef struct ppp_handler_info_t {
} ppp_handler_info_t;
typedef struct ppp_option_handler_info {
typedef struct ppp_simple_handler_info {
char name[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
const driver_parameter *settings;
bool isEnabled;
} ppp_option_handler_info;
typedef struct ppp_option_handler_info_t {
ppp_option_handler_info info;
uint8 _reserved_[_PPP_INFO_T_SIZE_ - sizeof(ppp_option_handler_info)];
} ppp_option_handler_info_t;
uint8 code;
// only PPPLCPExtension
} ppp_simple_handler_info;
typedef struct ppp_simple_handler_info_t {
ppp_simple_handler_info info;
uint8 _reserved_[_PPP_INFO_T_SIZE_ - sizeof(ppp_simple_handler_info)];
} ppp_simple_handler_info_t;
#endif

View File

@ -8,7 +8,7 @@
#ifndef _PPP_DEFS__H
#define _PPP_DEFS__H
#include <Errors.h>
#include <SupportDefs.h>
// various constants

View File

@ -18,7 +18,6 @@
// report flags
enum PPP_REPORT_FLAGS {
PPP_NO_REPORT_FLAGS = 0,
PPP_WAIT_FOR_REPLY = 0x1,
PPP_REMOVE_AFTER_REPORT = 0x2,
PPP_NO_REPLY_TIMEOUT = 0x4
@ -27,8 +26,11 @@ enum PPP_REPORT_FLAGS {
// report types
// the first 16 report types are reserved for the interface manager
enum PPP_REPORT_TYPE {
PPP_ALL_REPORTS = -1,
// used only when disabling reports
PPP_DESTRUCTION_REPORT = 16,
// the interface is being destroyed (no code is needed)
// this report is sent even if it was not requested
PPP_CONNECTION_REPORT = 17
};
@ -54,4 +56,11 @@ typedef struct ppp_report_packet {
} ppp_report_packet;
typedef struct ppp_report_request {
PPP_REPORT_TYPE type;
thread_id thread;
int32 flags;
} ppp_report_request;
#endif

View File

@ -13,6 +13,7 @@ R5KernelStaticLibrary kernelppp :
KPPPEncapsulator.cpp
KPPPInterface.cpp
KPPPLCP.cpp
KPPPLCPExtension.cpp
KPPPOptionHandler.cpp
KPPPProtocol.cpp
KPPPReportManager.cpp

View File

@ -15,7 +15,7 @@
PPPDevice::PPPDevice(const char *name, PPPInterface& interface,
driver_parameter *settings)
: fInterface(interface), fSettings(settings), fMTU(1500)
: fMTU(1500), fIsUp(false), fInterface(interface), fSettings(settings)
{
if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);

View File

@ -283,6 +283,23 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
SetAutoRedial(*((uint32*)data));
break;
case PPPC_ENABLE_INTERFACE_REPORTS: {
if(length < sizeof(ppp_report_request) || !data)
return B_ERROR;
ppp_report_request *request = (ppp_report_request*) data;
ReportManager().EnableReports(request->type, request->thread,
request->flags);
} break;
case PPPC_DISABLE_INTERFACE_REPORTS: {
if(length < sizeof(ppp_report_request) || !data)
return B_ERROR;
ppp_report_request *request = (ppp_report_request*) data;
ReportManager().DisableReports(request->type, request->thread);
} break;
case PPPC_CONTROL_DEVICE: {
if(length < sizeof(ppp_control_info) || !data)
return B_ERROR;

View File

@ -8,6 +8,7 @@
#include <KPPPInterface.h>
#include <KPPPDevice.h>
#include <KPPPEncapsulator.h>
#include <KPPPLCPExtension.h>
#include <KPPPOptionHandler.h>
#include <LockerHelper.h>
@ -19,9 +20,6 @@
#define PPP_PROTOCOL_OVERHEAD 2
// TODO:
// - add LCP extension handlers
PPPLCP::PPPLCP(PPPInterface& interface)
: PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL,
@ -80,6 +78,48 @@ PPPLCP::OptionHandlerAt(int32 index) const
return handler;
}
bool
PPPLCP::AddLCPExtension(PPPLCPExtension *extension)
{
if(!extension)
return false;
LockerHelper locker(StateMachine().Locker());
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
return fLCPExtensions.AddItem(extension);
}
bool
PPPLCP::RemoveLCPExtension(PPPLCPExtension *extension)
{
LockerHelper locker(StateMachine().Locker());
if(Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
return fLCPExtensions.RemoveItem(extension);
}
PPPLCPExtension*
PPPLCP::LCPExtensionAt(int32 index) const
{
PPPLCPExtension *extension = fLCPExtensions.ItemAt(index);
if(extension == fLCPExtensions.GetDefaultItem())
return NULL;
return extension;
}
uint32
PPPLCP::AdditionalOverhead() const
{
@ -163,11 +203,28 @@ PPPLCP::Receive(struct mbuf *packet, uint16 protocol)
case PPP_ECHO_REPLY:
case PPP_DISCARD_REQUEST:
m_freem(packet);
// do nothing
break;
default:
StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT);
default: {
status_t result = PPP_UNHANDLED;
// try to find LCP extensions that can handle this code
PPPLCPExtension *extension;
for(int32 index = 0; index < CountLCPExtensions(); index++) {
extension = LCPExtensionAt(index);
if(extension->IsEnabled() && extension->Code() == data->code)
result = extension->Receive(packet, data->code);
}
if(result == PPP_UNHANDLED) {
StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT);
return PPP_REJECTED;
}
return result;
}
}
return B_OK;
@ -178,4 +235,7 @@ void
PPPLCP::Pulse()
{
StateMachine().TimerEvent();
for(int32 index = 0; index < CountLCPExtensions(); index++)
LCPExtensionAt(index)->Pulse();
}

View File

@ -0,0 +1,84 @@
//----------------------------------------------------------------------
// 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 <KPPPLCPExtension.h>
#include <PPPControl.h>
PPPLCPExtension::PPPLCPExtension(const char *name, uint8 code, PPPInterface& interface,
driver_parameter *settings)
: fInterface(interface), fSettings(settings), fCode(code), fEnabled(true)
{
if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0;
} else
strcpy(fName, "???");
interface.LCP().AddLCPExtension(this);
}
PPPLCPExtension::~PPPLCPExtension()
{
Interface().LCP().RemoveLCPExtension(this);
}
status_t
PPPLCPExtension::InitCheck() const
{
if(!Settings())
return B_ERROR;
return B_OK;
}
status_t
PPPLCPExtension::Control(uint32 op, void *data, size_t length)
{
switch(op) {
case PPPC_GET_SIMPLE_HANDLER_INFO: {
if(length < sizeof(ppp_simple_handler_info_t) || !data)
return B_ERROR;
ppp_simple_handler_info *info = (ppp_simple_handler_info*) data;
memset(info, 0, sizeof(ppp_simple_handler_info_t));
strcpy(info->name, Name());
info->settings = Settings();
info->isEnabled = IsEnabled();
} break;
case PPPC_SET_ENABLED:
if(length < sizeof(uint32) || !data)
return B_ERROR;
SetEnabled(*((uint32*)data));
break;
default:
return PPP_UNHANDLED;
}
return B_OK;
}
void
PPPLCPExtension::Reset()
{
// do nothing by default
}
void
PPPLCPExtension::Pulse()
{
// do nothing by default
}

View File

@ -12,7 +12,7 @@
PPPOptionHandler::PPPOptionHandler(const char *name, PPPInterface& interface,
driver_parameter *settings)
: fInterface(interface), fSettings(settings)
: fInterface(interface), fSettings(settings), fEnabled(true)
{
if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
@ -44,12 +44,12 @@ status_t
PPPOptionHandler::Control(uint32 op, void *data, size_t length)
{
switch(op) {
case PPPC_GET_OPTION_HANDLER_INFO: {
if(length < sizeof(ppp_option_handler_info) || !data)
case PPPC_GET_SIMPLE_HANDLER_INFO: {
if(length < sizeof(ppp_simple_handler_info_t) || !data)
return B_ERROR;
ppp_option_handler_info *info = (ppp_option_handler_info*) data;
memset(info, 0, sizeof(ppp_option_handler_info));
ppp_simple_handler_info *info = (ppp_simple_handler_info*) data;
memset(info, 0, sizeof(ppp_simple_handler_info_t));
strcpy(info->name, Name());
info->settings = Settings();
info->isEnabled = IsEnabled();

View File

@ -28,7 +28,7 @@ PPPReportManager::~PPPReportManager()
void
PPPReportManager::EnableReports(PPP_REPORT_TYPE type, thread_id thread,
int32 flags = PPP_NO_REPORT_FLAGS)
int32 flags = PPP_NO_FLAGS)
{
LockerHelper locker(fLock);
@ -54,7 +54,7 @@ PPPReportManager::DisableReports(PPP_REPORT_TYPE type, thread_id thread)
if(request->thread != thread)
continue;
if(request->type == type)
if(request->type == type || request->type == PPP_ALL_REPORTS)
fReportRequests.RemoveItem(request);
}
}

View File

@ -11,6 +11,7 @@
#include <KPPPConfigurePacket.h>
#include <KPPPDevice.h>
#include <KPPPEncapsulator.h>
#include <KPPPLCPExtension.h>
#include <KPPPOptionHandler.h>
#include <net/if.h>
@ -701,16 +702,19 @@ PPPStateMachine::RCRGoodEvent(struct mbuf *packet)
case PPP_INITIAL_STATE:
case PPP_STARTING_STATE:
IllegalEvent(PPP_RCR_GOOD_EVENT);
m_freem(packet);
break;
case PPP_CLOSED_STATE:
locker.UnlockNow();
SendTerminateAck(packet);
SendTerminateAck();
m_freem(packet);
break;
case PPP_STOPPED_STATE:
// irc,scr,sca/8
// XXX: should we do nothing and wait for DownEvent()?
m_freem(packet);
break;
case PPP_REQ_SENT_STATE:
@ -740,7 +744,7 @@ PPPStateMachine::RCRGoodEvent(struct mbuf *packet)
break;
default:
;
m_freem(packet);
}
}
@ -759,7 +763,7 @@ PPPStateMachine::RCRBadEvent(struct mbuf *nak, struct mbuf *reject)
case PPP_CLOSED_STATE:
locker.UnlockNow();
SendTerminateAck(NULL);
SendTerminateAck();
break;
case PPP_STOPPED_STATE:
@ -787,11 +791,17 @@ PPPStateMachine::RCRBadEvent(struct mbuf *nak, struct mbuf *reject)
SendConfigureNak(nak);
else if(reject && ntohs(mtod(reject, ppp_lcp_packet*)->length) > 3)
SendConfigureNak(reject);
break;
return;
// prevents the nak/reject from being m_freem()'d
default:
;
}
if(nak)
m_freem(nak);
if(reject)
m_freem(reject);
}
@ -806,12 +816,13 @@ PPPStateMachine::RCAEvent(struct mbuf *packet)
// TODO:
// log this event
m_freem(packet);
return;
}
PPPOptionHandler *handler;
// let the option handlers parse this ack
PPPConfigurePacket ack(packet);
PPPOptionHandler *handler;
for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
handler = LCP().OptionHandlerAt(index);
handler->ParseAck(&ack);
@ -826,7 +837,7 @@ PPPStateMachine::RCAEvent(struct mbuf *packet)
case PPP_CLOSED_STATE:
case PPP_STOPPED_STATE:
locker.UnlockNow();
SendTerminateAck(NULL);
SendTerminateAck();
break;
case PPP_REQ_SENT_STATE:
@ -859,6 +870,8 @@ PPPStateMachine::RCAEvent(struct mbuf *packet)
default:
;
}
m_freem(packet);
}
@ -873,12 +886,13 @@ PPPStateMachine::RCNEvent(struct mbuf *packet)
// TODO:
// log this event
m_freem(packet);
return;
}
PPPOptionHandler *handler;
// let the option handlers parse this nak/reject
PPPConfigurePacket nak_reject(packet);
PPPOptionHandler *handler;
for(int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
handler = LCP().OptionHandlerAt(index);
@ -897,7 +911,7 @@ PPPStateMachine::RCNEvent(struct mbuf *packet)
case PPP_CLOSED_STATE:
case PPP_STOPPED_STATE:
locker.UnlockNow();
SendTerminateAck(packet);
SendTerminateAck();
break;
case PPP_REQ_SENT_STATE:
@ -923,6 +937,8 @@ PPPStateMachine::RCNEvent(struct mbuf *packet)
default:
;
}
m_freem(packet);
}
@ -943,6 +959,7 @@ PPPStateMachine::RTREvent(struct mbuf *packet)
case PPP_INITIAL_STATE:
case PPP_STARTING_STATE:
IllegalEvent(PPP_RTR_EVENT);
m_freem(packet);
break;
case PPP_ACK_RCVD_STATE:
@ -984,6 +1001,7 @@ PPPStateMachine::RTAEvent(struct mbuf *packet)
// TODO:
// log this event
m_freem(packet);
return;
}
@ -1019,12 +1037,15 @@ PPPStateMachine::RTAEvent(struct mbuf *packet)
default:
;
}
m_freem(packet);
}
// receive unknown code
void
PPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocol, uint8 type = PPP_PROTOCOL_REJECT)
PPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocol,
uint8 code = PPP_PROTOCOL_REJECT)
{
LockerHelper locker(fLock);
@ -1032,11 +1053,12 @@ PPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocol, uint8 type = PPP
case PPP_INITIAL_STATE:
case PPP_STARTING_STATE:
IllegalEvent(PPP_RUC_EVENT);
m_freem(packet);
break;
default:
locker.UnlockNow();
SendCodeReject(packet, protocol, type);
SendCodeReject(packet, protocol, code);
}
}
@ -1102,6 +1124,8 @@ PPPStateMachine::RXJBadEvent(struct mbuf *packet)
SendTerminateRequest();
break;
}
m_freem(packet);
}
@ -1120,11 +1144,13 @@ PPPStateMachine::RXREvent(struct mbuf *packet)
case PPP_OPENED_STATE:
if(echo->code == PPP_ECHO_REQUEST)
SendEchoReply(packet);
break;
return;
default:
;
}
m_freem(packet);
}
@ -1199,6 +1225,7 @@ PPPStateMachine::RCREvent(struct mbuf *packet)
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)
@ -1226,14 +1253,34 @@ PPPStateMachine::RCREvent(struct mbuf *packet)
void
PPPStateMachine::RXJEvent(struct mbuf *packet)
{
ppp_lcp_packet *reject mtod(packet, ppp_lcp_packet*);
ppp_lcp_packet *reject = mtod(packet, ppp_lcp_packet*);
if(reject->code == PPP_CODE_REJECT) {
// we only have basic codes, so there must be something wrong
if(Interface()->IsMultilink() && !Interface()->Parent())
CloseEvent();
else
RXJBadEvent(packet);
uint8 rejectedCode = reject->data[0];
// test if the rejected code belongs to the minimum LCP requirements
if(rejectedCode >= PPP_MIN_LCP_CODE && rejectedCode <= PPP_MAX_LCP_CODE) {
if(Interface()->IsMultilink() && !Interface()->Parent()) {
// Main interfaces do not have states between STARTING and OPENED.
// An RXJBadEvent() would enter one of those states which is bad.
m_freem(packet);
CloseEvent();
} else
RXJBadEvent(packet);
return;
}
// find the LCP extension and disable it
PPPLCPExtension *extension;
for(int32 index = 0; index < LCP().CountLCPExtensions(); index++) {
extension = LCP().LCPExtensionAt(index);
if(extension->Code() == rejectedCode)
extension->SetEnabled(false);
}
m_freem(packet);
} else if(reject->code == PPP_PROTOCOL_REJECT) {
// disable all handlers for rejected protocol type
uint16 rejected = *((uint16*) reject->data);
@ -1245,6 +1292,7 @@ PPPStateMachine::RXJEvent(struct mbuf *packet)
return;
}
// disable protocols and encapsulators with the rejected protocl number
int32 index;
PPPProtocol *protocol_handler;
PPPEncapsulator *encapsulator_handler = Interface()->FirstEncapsulator();
@ -1264,10 +1312,13 @@ PPPStateMachine::RXJEvent(struct mbuf *packet)
}
RXJGoodEvent(packet);
// this event handler does not m_freem(packet)!!!
// notify parent, too
if(Interface()->Parent())
Interface()->Parent()->StateMachine().RXJEvent(packet);
else
m_freem(packet);
}
}
@ -1374,9 +1425,13 @@ PPPStateMachine::SendConfigureRequest()
void
PPPStateMachine::SendConfigureAck(struct mbuf *packet)
{
if(!packet)
return;
mtod(packet, ppp_lcp_packet*)->code = PPP_CONFIGURE_ACK;
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);
@ -1387,6 +1442,9 @@ PPPStateMachine::SendConfigureAck(struct mbuf *packet)
void
PPPStateMachine::SendConfigureNak(struct mbuf *packet)
{
if(!packet)
return;
ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*);
if(nak->code == PPP_CONFIGURE_NAK) {
if(fNakCounter == 0) {
@ -1424,7 +1482,7 @@ PPPStateMachine::SendTerminateRequest()
void
PPPStateMachine::SendTerminateAck(struct mbuf *request)
PPPStateMachine::SendTerminateAck(struct mbuf *request = NULL)
{
struct mbuf *reply = request;
@ -1440,26 +1498,32 @@ PPPStateMachine::SendTerminateAck(struct mbuf *request)
ack = mtod(reply, ppp_lcp_packet*);
ack->id = NextID();
ack->length = 4;
}
ack = mtod(reply, ppp_lcp_packet*);
ack->code = PPP_TERMINATE_ACK;
ack->length = 4;
LCP().Send(reply);
}
void
PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type)
PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 code)
{
if(!packet)
return;
int32 length;
// additional space needed for this reject
if(type == PPP_PROTOCOL_REJECT)
if(code == PPP_PROTOCOL_REJECT)
length = 6;
else
length = 4;
M_PREPEND(packet, length);
// add some space for the header
int32 adjust = 0;
// adjust packet size by this value if packet is too big
if(packet->m_flags & M_PKTHDR) {
@ -1472,7 +1536,7 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type
m_adj(packet, adjust);
ppp_lcp_packet *reject = mtod(packet, ppp_lcp_packet*);
reject->code = type;
reject->code = code;
reject->id = NextID();
if(packet->m_flags & M_PKTHDR)
reject->length = htons(packet->m_pkthdr.len);
@ -1480,7 +1544,7 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type
reject->length = htons(packet->m_len);
protocol = htons(protocol);
if(type == PPP_PROTOCOL_REJECT)
if(code == PPP_PROTOCOL_REJECT)
memcpy(&reject->data, &protocol, sizeof(protocol));
LCP().Send(packet);
@ -1490,6 +1554,9 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type
void
PPPStateMachine::SendEchoReply(struct mbuf *request)
{
if(!request)
return;
ppp_lcp_packet *reply = mtod(request, ppp_lcp_packet*);
reply->code = PPP_ECHO_REPLY;
// the request becomes a reply
@ -1589,4 +1656,7 @@ PPPStateMachine::ResetOptionHandlers()
{
for(int32 index = 0; index < LCP().CountOptionHandlers(); index++)
LCP().OptionHandlerAt(index)->Reset();
for(int32 index = 0; index < LCP().CountLCPExtensions(); index++)
LCP().LCPExtensionAt(index)->Reset();
}