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 PPP_RXR_EVENT
}; };
// LCP protocol types as defined in RFC 1661 // LCP protocol codes as defined in RFC 1661
// ToDo: add LCP extensions // ToDo: add LCP extensions
enum PPP_LCP_TYPE { enum PPP_LCP_CODE {
PPP_CONFIGURE_REQUEST = 1, PPP_CONFIGURE_REQUEST = 1,
PPP_CONFIGURE_ACK = 2, PPP_CONFIGURE_ACK = 2,
PPP_CONFIGURE_NAK = 3, PPP_CONFIGURE_NAK = 3,

View File

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

View File

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

View File

@ -23,6 +23,7 @@
#endif #endif
class PPPEncapsulator; class PPPEncapsulator;
class PPPLCPExtension;
class PPPOptionHandler; class PPPOptionHandler;
@ -30,7 +31,7 @@ typedef struct ppp_lcp_packet {
uint8 code; uint8 code;
uint8 id; uint8 id;
uint16 length; uint16 length;
int8 data[0]; uint8 data[0];
} ppp_lcp_packet; } ppp_lcp_packet;
@ -56,6 +57,12 @@ class PPPLCP : public PPPProtocol {
{ return fOptionHandlers.CountItems(); } { return fOptionHandlers.CountItems(); }
PPPOptionHandler *OptionHandlerAt(int32 index) const; 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 PPPEncapsulator *Target() const
{ return fTarget; } { return fTarget; }
void SetTarget(PPPEncapsulator *target) void SetTarget(PPPEncapsulator *target)
@ -78,6 +85,7 @@ class PPPLCP : public PPPProtocol {
PPPStateMachine& fStateMachine; PPPStateMachine& fStateMachine;
List<PPPOptionHandler*> fOptionHandlers; List<PPPOptionHandler*> fOptionHandlers;
List<PPPLCPExtension*> fLCPExtensions;
PPPEncapsulator *fTarget; 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 #ifndef _K_PPP_OPTION_HANDLER__H
#define _K_PPP_OPTION_HANDLER__H #define _K_PPP_OPTION_HANDLER__H
#include <driver_settings.h>
#include <KPPPDefs.h> #include <KPPPDefs.h>
#ifndef _K_PPP_INTERFACE__H #ifndef _K_PPP_INTERFACE__H
@ -35,7 +33,8 @@ class PPPOptionHandler {
driver_parameter *Settings() const driver_parameter *Settings() const
{ return fSettings; } { return fSettings; }
void SetEnabled(bool enabled = true); void SetEnabled(bool enabled = true)
{ fEnabled = enabled; }
bool IsEnabled() const bool IsEnabled() const
{ return fEnabled; } { 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 <OS.h>
#include <KPPPReportDefs.h> #include <KPPPDefs.h>
#include <PPPReportDefs.h>
#include <List.h> #include <List.h>
@ -23,7 +24,7 @@ class PPPReportManager {
~PPPReportManager(); ~PPPReportManager();
void EnableReports(PPP_REPORT_TYPE type, thread_id thread, 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); void DisableReports(PPP_REPORT_TYPE type, thread_id thread);
bool DoesReport(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); bool Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length);

View File

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

View File

@ -22,7 +22,6 @@
#define PPP_OPTION_HANDLER_OPS_START PPP_OPS_START + 5 * PPP_RESERVE_OPS_COUNT #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_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_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 #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_DIAL_ON_DEMAND,
PPPC_SET_AUTO_REDIAL, 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 // handler access
PPPC_CONTROL_DEVICE, PPPC_CONTROL_DEVICE,
PPPC_CONTROL_PROTOCOL, PPPC_CONTROL_PROTOCOL,
@ -49,31 +53,13 @@ enum PPP_CONTROL_OPS {
PPPC_SET_MTU, PPPC_SET_MTU,
// ----------------------------------------------------- // -----------------------------------------------------
// -----------------------------------------------------
// PPPProtocol
// -----------------------------------------------------
// -----------------------------------------------------
// PPPEncapsulator
// -----------------------------------------------------
// -----------------------------------------------------
// PPPOptionHandler
PPPC_GET_OPTION_HANDLER_INFO = PPP_OPTION_HANDLER_OPS_START,
// -----------------------------------------------------
// -----------------------------------------------------
// PPPLCPExtension
// -----------------------------------------------------
// ----------------------------------------------------- // -----------------------------------------------------
// Common/mixed ops // Common/mixed ops
PPPC_GET_HANDLER_INFO = PPP_COMMON_OPS_START, PPPC_GET_HANDLER_INFO = PPP_COMMON_OPS_START,
// PPPProtocol and PPPEncapsulator
PPPC_SET_ENABLED, PPPC_SET_ENABLED,
// ----------------------------------------------------- PPPC_GET_SIMPLE_HANDLER_INFO,
// PPPOptionHandler and PPPLCPExtension
// -----------------------------------------------------
// PPPProtocol and PPPEncapsulator
// ----------------------------------------------------- // -----------------------------------------------------
PPP_CONTROL_OPS_END = B_DEVICE_OP_CODES_END + 0xFFFF PPP_CONTROL_OPS_END = B_DEVICE_OP_CODES_END + 0xFFFF
@ -166,17 +152,19 @@ typedef struct ppp_handler_info_t {
} 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]; char name[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
const driver_parameter *settings; const driver_parameter *settings;
bool isEnabled; bool isEnabled;
} ppp_option_handler_info;
typedef struct ppp_option_handler_info_t { uint8 code;
ppp_option_handler_info info; // only PPPLCPExtension
uint8 _reserved_[_PPP_INFO_T_SIZE_ - sizeof(ppp_option_handler_info)]; } ppp_simple_handler_info;
} ppp_option_handler_info_t; 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 #endif

View File

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

View File

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

View File

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

View File

@ -15,7 +15,7 @@
PPPDevice::PPPDevice(const char *name, PPPInterface& interface, PPPDevice::PPPDevice(const char *name, PPPInterface& interface,
driver_parameter *settings) driver_parameter *settings)
: fInterface(interface), fSettings(settings), fMTU(1500) : fMTU(1500), fIsUp(false), fInterface(interface), fSettings(settings)
{ {
if(name) { if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); 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)); SetAutoRedial(*((uint32*)data));
break; 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: { case PPPC_CONTROL_DEVICE: {
if(length < sizeof(ppp_control_info) || !data) if(length < sizeof(ppp_control_info) || !data)
return B_ERROR; return B_ERROR;

View File

@ -8,6 +8,7 @@
#include <KPPPInterface.h> #include <KPPPInterface.h>
#include <KPPPDevice.h> #include <KPPPDevice.h>
#include <KPPPEncapsulator.h> #include <KPPPEncapsulator.h>
#include <KPPPLCPExtension.h>
#include <KPPPOptionHandler.h> #include <KPPPOptionHandler.h>
#include <LockerHelper.h> #include <LockerHelper.h>
@ -19,9 +20,6 @@
#define PPP_PROTOCOL_OVERHEAD 2 #define PPP_PROTOCOL_OVERHEAD 2
// TODO:
// - add LCP extension handlers
PPPLCP::PPPLCP(PPPInterface& interface) PPPLCP::PPPLCP(PPPInterface& interface)
: PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL, : PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL,
@ -80,6 +78,48 @@ PPPLCP::OptionHandlerAt(int32 index) const
return handler; 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 uint32
PPPLCP::AdditionalOverhead() const PPPLCP::AdditionalOverhead() const
{ {
@ -163,11 +203,28 @@ PPPLCP::Receive(struct mbuf *packet, uint16 protocol)
case PPP_ECHO_REPLY: case PPP_ECHO_REPLY:
case PPP_DISCARD_REQUEST: case PPP_DISCARD_REQUEST:
m_freem(packet);
// do nothing // do nothing
break; break;
default: default: {
StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT); 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; return B_OK;
@ -178,4 +235,7 @@ void
PPPLCP::Pulse() PPPLCP::Pulse()
{ {
StateMachine().TimerEvent(); 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, PPPOptionHandler::PPPOptionHandler(const char *name, PPPInterface& interface,
driver_parameter *settings) driver_parameter *settings)
: fInterface(interface), fSettings(settings) : fInterface(interface), fSettings(settings), fEnabled(true)
{ {
if(name) { if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
@ -44,12 +44,12 @@ status_t
PPPOptionHandler::Control(uint32 op, void *data, size_t length) PPPOptionHandler::Control(uint32 op, void *data, size_t length)
{ {
switch(op) { switch(op) {
case PPPC_GET_OPTION_HANDLER_INFO: { case PPPC_GET_SIMPLE_HANDLER_INFO: {
if(length < sizeof(ppp_option_handler_info) || !data) if(length < sizeof(ppp_simple_handler_info_t) || !data)
return B_ERROR; return B_ERROR;
ppp_option_handler_info *info = (ppp_option_handler_info*) data; ppp_simple_handler_info *info = (ppp_simple_handler_info*) data;
memset(info, 0, sizeof(ppp_option_handler_info)); memset(info, 0, sizeof(ppp_simple_handler_info_t));
strcpy(info->name, Name()); strcpy(info->name, Name());
info->settings = Settings(); info->settings = Settings();
info->isEnabled = IsEnabled(); info->isEnabled = IsEnabled();

View File

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

View File

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