Finished first set of needed features (tests will follow as soon as the needed kernel modules are available).

Next step will be to add:
- Protocol-Field-Compression support (including PFC handler)
- MRU option handler
- ?simple authentication option handler (helper class)?


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4513 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald
2003-09-06 01:00:12 +00:00
parent 8d1a0ee7c1
commit a602502a7e
22 changed files with 757 additions and 365 deletions
@@ -45,6 +45,8 @@ class PPPConfigurePacket {
int32 CountItems() const int32 CountItems() const
{ return fItems.CountItems(); } { return fItems.CountItems(); }
ppp_configure_item *ItemAt(int32 index) const; ppp_configure_item *ItemAt(int32 index) const;
bool HasItemWithType(uint8 type) const;
ppp_configure_item *ItemWithType(uint8 type) const;
struct mbuf *ToMbuf(uint32 reserve = 0); struct mbuf *ToMbuf(uint32 reserve = 0);
// the user is responsible for freeing the mbuf // the user is responsible for freeing the mbuf
+3 -2
View File
@@ -18,8 +18,9 @@ typedef uint32 interface_id;
// module key types (used when loading a module) // module key types (used when loading a module)
enum { enum PPP_MODULE_KEY_TYPE {
PPP_LOAD_MODULE_TYPE, PPP_UNDEFINED_KEY_TYPE = -1,
PPP_LOAD_MODULE_TYPE = 0,
PPP_DEVICE_TYPE, PPP_DEVICE_TYPE,
PPP_PROTOCOL_TYPE, PPP_PROTOCOL_TYPE,
PPP_AUTHENTICATOR_TYPE, PPP_AUTHENTICATOR_TYPE,
+3 -7
View File
@@ -19,7 +19,7 @@
class PPPDevice { class PPPDevice {
public: public:
PPPDevice(const char *name, uint32 overhead, PPPInterface *interface, PPPDevice(const char *name, PPPInterface& interface,
driver_parameter *settings); driver_parameter *settings);
virtual ~PPPDevice(); virtual ~PPPDevice();
@@ -28,10 +28,7 @@ class PPPDevice {
const char *Name() const const char *Name() const
{ return fName; } { return fName; }
uint32 Overhead() const PPPInterface& Interface() const
{ return fOverhead; }
PPPInterface *Interface() const
{ return fInterface; } { return fInterface; }
driver_parameter *Settings() const driver_parameter *Settings() const
{ return fSettings; } { return fSettings; }
@@ -85,8 +82,7 @@ class PPPDevice {
private: private:
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1]; char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
uint32 fOverhead; PPPInterface& fInterface;
PPPInterface *fInterface;
driver_parameter *fSettings; driver_parameter *fSettings;
uint32 fMTU; uint32 fMTU;
@@ -24,7 +24,7 @@ class PPPEncapsulator {
PPPEncapsulator(const char *name, PPP_PHASE phase, PPPEncapsulator(const char *name, PPP_PHASE phase,
PPP_ENCAPSULATION_LEVEL level, uint16 protocol, PPP_ENCAPSULATION_LEVEL level, uint16 protocol,
int32 addressFamily, uint32 overhead, int32 addressFamily, uint32 overhead,
PPPInterface *interface, driver_parameter *settings, PPPInterface& interface, driver_parameter *settings,
int32 flags = PPP_NO_FLAGS); int32 flags = PPP_NO_FLAGS);
virtual ~PPPEncapsulator(); virtual ~PPPEncapsulator();
@@ -41,7 +41,7 @@ class PPPEncapsulator {
uint32 Overhead() const uint32 Overhead() const
{ return fOverhead; } { return fOverhead; }
PPPInterface *Interface() const PPPInterface& Interface() const
{ return fInterface; } { return fInterface; }
driver_parameter *Settings() const driver_parameter *Settings() const
{ return fSettings; } { return fSettings; }
@@ -58,8 +58,6 @@ class PPPEncapsulator {
bool IsEnabled() const bool IsEnabled() const
{ return fEnabled; } { return fEnabled; }
void SetUpRequested(bool requested = true)
{ fUpRequested = requested; }
bool IsUpRequested() const bool IsUpRequested() const
{ return fUpRequested; } { return fUpRequested; }
@@ -92,6 +90,9 @@ class PPPEncapsulator {
virtual void Pulse(); virtual void Pulse();
protected: protected:
void SetUpRequested(bool requested = true)
{ fUpRequested = requested; }
void UpStarted(); void UpStarted();
void DownStarted(); void DownStarted();
@@ -109,7 +110,7 @@ class PPPEncapsulator {
PPP_ENCAPSULATION_LEVEL fLevel; PPP_ENCAPSULATION_LEVEL fLevel;
uint16 fProtocol; uint16 fProtocol;
int32 fAddressFamily; int32 fAddressFamily;
PPPInterface *fInterface; PPPInterface& fInterface;
driver_parameter *fSettings; driver_parameter *fSettings;
int32 fFlags; int32 fFlags;
+12 -8
View File
@@ -74,12 +74,13 @@ class PPPInterface {
bigtime_t DisconnectAfterIdleSince() const bigtime_t DisconnectAfterIdleSince() const
{ return fDisconnectAfterIdleSince; } { return fDisconnectAfterIdleSince; }
void SetLinkMTU(uint32 linkMTU); void SetMRU(uint32 MRU);
uint32 LinkMTU() const
{ return fLinkMTU; }
// this is the smallest MTU that we and the peer have
uint32 MRU() const uint32 MRU() const
{ return fMRU; } { return fMRU; }
// this is the smallest MRU that we and the peer have
uint32 InterfaceMTU() const
{ return fInterfaceMTU; }
// this is the MRU including encapsulator overhead
status_t Control(uint32 op, void *data, size_t length); status_t Control(uint32 op, void *data, size_t length);
@@ -92,12 +93,14 @@ class PPPInterface {
int32 CountProtocols() const int32 CountProtocols() const
{ return fProtocols.CountItems(); } { return fProtocols.CountItems(); }
PPPProtocol *ProtocolAt(int32 index) const; PPPProtocol *ProtocolAt(int32 index) const;
PPPProtocol *ProtocolFor(uint16 protocol, int32 start = 0) const; PPPProtocol *ProtocolFor(uint16 protocol, int32 *start = NULL) const;
int32 IndexOfProtocol(PPPProtocol *protocol) const int32 IndexOfProtocol(PPPProtocol *protocol) const
{ return fProtocols.IndexOf(protocol); } { return fProtocols.IndexOf(protocol); }
bool AddEncapsulator(PPPEncapsulator *encapsulator); bool AddEncapsulator(PPPEncapsulator *encapsulator);
bool RemoveEncapsulator(PPPEncapsulator *encapsulator); bool RemoveEncapsulator(PPPEncapsulator *encapsulator);
int32 CountEncapsulators() const;
PPPEncapsulator *EncapsulatorAt(int32 index) const;
PPPEncapsulator *FirstEncapsulator() const PPPEncapsulator *FirstEncapsulator() const
{ return fFirstEncapsulator; } { return fFirstEncapsulator; }
PPPEncapsulator *EncapsulatorFor(uint16 protocol, PPPEncapsulator *EncapsulatorFor(uint16 protocol,
@@ -144,7 +147,7 @@ class PPPInterface {
bool LoadModules(driver_settings *settings, bool LoadModules(driver_settings *settings,
int32 start, int32 count); int32 start, int32 count);
bool LoadModule(const char *name, driver_parameter *parameter, bool LoadModule(const char *name, driver_parameter *parameter,
int32 type); PPP_MODULE_KEY_TYPE type);
status_t Send(struct mbuf *packet, uint16 protocol); status_t Send(struct mbuf *packet, uint16 protocol);
status_t Receive(struct mbuf *packet, uint16 protocol); status_t Receive(struct mbuf *packet, uint16 protocol);
@@ -164,7 +167,7 @@ class PPPInterface {
// saves the returned ifnet structure // saves the returned ifnet structure
bool UnregisterInterface(); bool UnregisterInterface();
void CalculateMRU(); void CalculateInterfaceMTU();
void CalculateBaudRate(); void CalculateBaudRate();
void Redial(); void Redial();
@@ -191,7 +194,7 @@ class PPPInterface {
ppp_manager_info *fManager; ppp_manager_info *fManager;
bigtime_t fIdleSince, fDisconnectAfterIdleSince; bigtime_t fIdleSince, fDisconnectAfterIdleSince;
uint32 fLinkMTU, fMRU, fHeaderLength; uint32 fMRU, fInterfaceMTU, fHeaderLength;
PPPInterface *fParent; PPPInterface *fParent;
List<PPPInterface*> fChildren; List<PPPInterface*> fChildren;
@@ -211,6 +214,7 @@ class PPPInterface {
BLocker& fLock; BLocker& fLock;
status_t fInitStatus; status_t fInitStatus;
int32 fDeleteCounter;
}; };
@@ -28,6 +28,7 @@ typedef struct ppp_manager_info {
// you should always create interfaces using this function // you should always create interfaces using this function
void (*delete_interface)(interface_id ID); void (*delete_interface)(interface_id ID);
// this marks the interface for deletion // this marks the interface for deletion
void (*remove_interface)(interface_id ID);
ifnet* (*register_interface)(interface_id ID); ifnet* (*register_interface)(interface_id ID);
bool (*unregister_interface)(interface_id ID); bool (*unregister_interface)(interface_id ID);
+5 -4
View File
@@ -16,11 +16,12 @@ class PPPInterface;
typedef struct ppp_module_info { typedef struct ppp_module_info {
module_info minfo; module_info minfo;
status_t (*control)(uint32 op, void *data, size_t length); status_t (*control)(uint32 op, void *data, size_t length);
status_t (*add_to)(PPPInterface *mainInterface, PPPInterface *subInterface, status_t (*add_to)(PPPInterface& mainInterface, PPPInterface *subInterface,
driver_parameter *settings, int32 type); driver_parameter *settings, PPP_MODULE_KEY_TYPE type);
// multilink: handlers that must run on a real device // multilink: handlers that must run on a real device
// should be added to subInterface while mainInterface // should be added to subInterface (may be NULL)
// handlers are used for the bundle of interfaces // while mainInterface handlers are used for the
// bundle of interfaces
} ppp_module_info; } ppp_module_info;
@@ -21,23 +21,25 @@ class PPPConfigurePacket;
class PPPOptionHandler { class PPPOptionHandler {
public: public:
PPPOptionHandler(const char *name, PPPInterface *interface, PPPOptionHandler(const char *name, PPPInterface& interface,
driver_parameter *settings); driver_parameter *settings);
virtual ~PPPOptionHandler(); virtual ~PPPOptionHandler();
virtual status_t InitCheck() const; 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); void SetEnabled(bool enabled = true);
bool IsEnabled() const bool IsEnabled() const
{ return fEnabled; } { return fEnabled; }
const char *Name() const virtual status_t Control(uint32 op, void *data, size_t length);
{ return fName; }
PPPInterface *Interface() const
{ return fInterface; }
driver_parameter *Settings() const
{ return fSettings; }
virtual void Reset() = 0; virtual void Reset() = 0;
// e.g.: remove list of rejected values // e.g.: remove list of rejected values
@@ -61,7 +63,7 @@ class PPPOptionHandler {
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;
bool fEnabled; bool fEnabled;
@@ -18,7 +18,7 @@ class PPPInterface;
class PPPProtocol { class PPPProtocol {
public: public:
PPPProtocol(const char *name, PPP_PHASE phase, uint16 protocol, PPPProtocol(const char *name, PPP_PHASE phase, uint16 protocol,
int32 addressFamily, PPPInterface *interface, int32 addressFamily, PPPInterface& interface,
driver_parameter *settings, int32 flags = PPP_NO_FLAGS); driver_parameter *settings, int32 flags = PPP_NO_FLAGS);
virtual ~PPPProtocol(); virtual ~PPPProtocol();
@@ -30,7 +30,7 @@ class PPPProtocol {
PPP_PHASE Phase() const PPP_PHASE Phase() const
{ return fPhase; } { return fPhase; }
PPPInterface *Interface() const PPPInterface& Interface() const
{ return fInterface; } { return fInterface; }
driver_parameter *Settings() const driver_parameter *Settings() const
{ return fSettings; } { return fSettings; }
@@ -47,8 +47,6 @@ class PPPProtocol {
bool IsEnabled() const bool IsEnabled() const
{ return fEnabled; } { return fEnabled; }
void SetUpRequested(bool requested = true)
{ fUpRequested = requested; }
bool IsUpRequested() const bool IsUpRequested() const
{ return fUpRequested; } { return fUpRequested; }
@@ -71,6 +69,9 @@ class PPPProtocol {
virtual void Pulse(); virtual void Pulse();
protected: protected:
void SetUpRequested(bool requested = true)
{ fUpRequested = requested; }
void UpStarted(); void UpStarted();
void DownStarted(); void DownStarted();
@@ -84,7 +85,7 @@ class PPPProtocol {
PPP_PHASE fPhase; PPP_PHASE fPhase;
uint16 fProtocol; uint16 fProtocol;
int32 fAddressFamily; int32 fAddressFamily;
PPPInterface *fInterface; PPPInterface& fInterface;
driver_parameter *fSettings; driver_parameter *fSettings;
int32 fFlags; int32 fFlags;
@@ -8,6 +8,29 @@
#ifndef _K_PPP_UTILS__H #ifndef _K_PPP_UTILS__H
#define _K_PPP_UTILS__H #define _K_PPP_UTILS__H
#ifndef _K_PPP_DEFS__H
#include <KPPPDefs.h>
#endif
// helper functions
template<class T>
inline
bool
is_handler_allowed(T& handler, PPP_STATE state, PPP_PHASE phase)
{
if(handler.Protocol() == PPP_LCP_PROTOCOL)
return true;
else if(state != PPP_OPENED_STATE)
return false;
else if(phase > PPP_AUTHENTICATION_PHASE
|| (phase >= PPP_ESTABLISHMENT_PHASE
&& handler.Flags() & PPP_ALWAYS_ALLOWED))
return true;
else
return false;
}
// These are very simple send/receive_data functions with a timeout // These are very simple send/receive_data functions with a timeout
// and there is a race condition beween has_data() and send/receive_data(). // and there is a race condition beween has_data() and send/receive_data().
@@ -31,7 +31,7 @@ class LockerHelper {
public: public:
LockerHelper(BLocker& lock) : fLock(&lock) LockerHelper(BLocker& lock) : fLock(&lock)
{ {
if(fLock->Lock() != B_OK) if(!fLock->Lock())
fLock = NULL; fLock = NULL;
} }
+99 -33
View File
@@ -15,32 +15,27 @@
// starting values and other values for control ops // starting values and other values for control ops
#define PPP_RESERVE_OPS_COUNT 0xFFFF #define PPP_RESERVE_OPS_COUNT 0xFFFF
#define PPP_OPS_START B_DEVICE_OP_CODES_END + 1 #define PPP_OPS_START B_DEVICE_OP_CODES_END + 1
#define PPP_INTERFACE_OPS_START PPP_OPS_START + PPP_RESERVE_OPS_COUNT
#define PPP_DEVICE_OPS_START PPP_OPS_START + 2 * PPP_RESERVE_OPS_COUNT #define PPP_DEVICE_OPS_START PPP_OPS_START + 2 * PPP_RESERVE_OPS_COUNT
#define PPP_PROTOCOL_OPS_START PPP_OPS_START + 3 * PPP_RESERVE_OPS_COUNT #define PPP_PROTOCOL_OPS_START PPP_OPS_START + 3 * PPP_RESERVE_OPS_COUNT
#define PPP_ENCAPSULATOR_OPS_START PPP_OPS_START + 4 * PPP_RESERVE_OPS_COUNT #define PPP_ENCAPSULATOR_OPS_START PPP_OPS_START + 4 * PPP_RESERVE_OPS_COUNT
#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_PROTO_ENCAPS_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
enum PPP_CONTROL_OPS { enum PPP_CONTROL_OPS {
// ----------------------------------------------------- // -----------------------------------------------------
// PPPInterface // PPPInterface
PPPC_GET_STATUS = PPP_OPS_START, PPPC_GET_INTERFACE_INFO = PPP_INTERFACE_OPS_START,
PPPC_GET_MRU,
PPPC_SET_MRU, PPPC_SET_MRU,
PPPC_GET_LINK_MTU,
PPPC_SET_LINK_MTU,
PPPC_GET_DIAL_ON_DEMAND,
PPPC_SET_DIAL_ON_DEMAND, PPPC_SET_DIAL_ON_DEMAND,
PPPC_GET_AUTO_REDIAL,
PPPC_SET_AUTO_REDIAL, PPPC_SET_AUTO_REDIAL,
PPPC_GET_PROTOCOLS_COUNT,
PPPC_GET_ENCAPSULATORS_COUNT, // handler access
PPPC_GET_OPTION_HANDLERS_COUNT, PPPC_CONTROL_DEVICE,
PPPC_GET_LCP_EXTENSIONS_COUNT,
PPPC_GET_CHILDREN_COUNT,
PPPC_CONTROL_PROTOCOL, PPPC_CONTROL_PROTOCOL,
PPPC_CONTROL_ENCAPSULATOR, PPPC_CONTROL_ENCAPSULATOR,
PPPC_CONTROL_OPTION_HANDLER, PPPC_CONTROL_OPTION_HANDLER,
@@ -50,9 +45,8 @@ enum PPP_CONTROL_OPS {
// ----------------------------------------------------- // -----------------------------------------------------
// PPPDevice // PPPDevice
PPPC_GET_MTU = PPP_DEVICE_OPS_START, PPPC_GET_DEVICE_INFO = PPP_DEVICE_OPS_START,
PPPC_SET_MTU, PPPC_SET_MTU,
PPPC_GET_PREFERRED_MTU,
// ----------------------------------------------------- // -----------------------------------------------------
// ----------------------------------------------------- // -----------------------------------------------------
@@ -65,6 +59,7 @@ enum PPP_CONTROL_OPS {
// ----------------------------------------------------- // -----------------------------------------------------
// PPPOptionHandler // PPPOptionHandler
PPPC_GET_OPTION_HANDLER_INFO = PPP_OPTION_HANDLER_OPS_START,
// ----------------------------------------------------- // -----------------------------------------------------
// ----------------------------------------------------- // -----------------------------------------------------
@@ -72,45 +67,116 @@ enum PPP_CONTROL_OPS {
// ----------------------------------------------------- // -----------------------------------------------------
// ----------------------------------------------------- // -----------------------------------------------------
// PPPProtocol and PPPEncapsulator // Common/mixed ops
PPPC_GET_NAME, PPPC_GET_HANDLER_INFO = PPP_COMMON_OPS_START,
PPPC_GET_ENABLED = PPP_COMMON_PROTO_ENCAPS_OPS_START,
PPPC_SET_ENABLED, PPPC_SET_ENABLED,
// ----------------------------------------------------- // -----------------------------------------------------
// -----------------------------------------------------
// PPPProtocol and PPPEncapsulator
// -----------------------------------------------------
PPP_CONTROL_OPS_END = B_DEVICE_OP_CODES_END + 0xFFFF PPP_CONTROL_OPS_END = B_DEVICE_OP_CODES_END + 0xFFFF
}; };
typedef struct ppp_control_structure { typedef struct ppp_control_info {
uint32 index; uint32 index;
// index of interface/protocol/encapsulator/etc. // index of interface/protocol/encapsulator/etc.
uint32 op; uint32 op;
// the Control()/ioctl() opcode // the Control()/ioctl() opcode
void *data;
union {
void *data;
ppp_control_struct *subcontrol;
} pointer;
// either a pointer to the data or a pointer to a control structure for
// accessing protocols/encapsulators/etc.
size_t length; size_t length;
// not always needed // should always be set
} ppp_control_structure; } ppp_control_info;
typedef struct ppp_status_structure { // -----------------------------------------------------------
// structures for storing information about interface/handlers
// use the xxx_info_t structures when allocating memory (they
// reserve memory for future implementations)
// -----------------------------------------------------------
#define _PPP_INFO_T_SIZE_ 256
typedef struct ppp_interface_info {
const driver_settings *settings;
PPP_MODE mode; PPP_MODE mode;
PPP_STATE state; PPP_STATE state;
PPP_PHASE phase; PPP_PHASE phase;
PPP_AUTHENTICATION_STATUS authenticationStatus, peerAuthenticationStatus; PPP_AUTHENTICATION_STATUS authenticationStatus, peerAuthenticationStatus;
bigtime_t idle_since; uint32 protocolsCount, encapsulatorsCount, optionHandlersCount,
LCPExtensionsCount, childrenCount;
uint32 MRU, interfaceMTU;
uint8 _reserved_[64 - (sizeof(PPP_MODE) + sizeof(PPP_STATE) + sizeof(PPP_PHASE) bigtime_t idleSince, disconnectAfterIdleSince;
+ 2 * sizeof(PPP_AUTHENTICATION_STATUS) + sizeof(bigtime_t))];
} ppp_status_structure; bool doesDialOnDemand, doesAutoRedial, hasDevice, isMultilink, hasParent;
} ppp_interface_info;
typedef struct ppp_interface_info_t {
ppp_interface_info info;
uint8 _reserved_[_PPP_INFO_T_SIZE_ - sizeof(ppp_interface_info)];
} ppp_interface_info_t;
// devices are special handlers, so they have their own structure
typedef struct ppp_device_info {
char name[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
const driver_parameter *settings;
uint32 MTU, preferredMTU;
uint32 inputTransferRate, outputTransferRate, outputBytesCount;
} ppp_device_info;
typedef struct ppp_device_info_t {
ppp_device_info info;
uint8 _reserved_[_PPP_INFO_T_SIZE_ - sizeof(ppp_device_info)];
} ppp_device_info_t;
typedef struct ppp_handler_info {
char name[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
// general
const driver_parameter *settings;
PPP_PHASE phase;
int32 addressFamily, flags;
uint16 protocol;
bool isEnabled;
// only protocol and encapsulator
bool isUpRequested;
PPP_PHASE connectionStatus;
// there are four possible states:
// PPP_ESTABLISHED_PHASE - IsUp() == true
// PPP_DOWN_PHASE - IsDown() == true
// PPP_ESTABLISHMENT_PHASE - IsGoingUp() == true
// PPP_TERMINATION_PHASE - IsGoingDown() == true
// only encapsulator
PPP_ENCAPSULATION_LEVEL level;
uint32 overhead;
} ppp_handler_info;
typedef struct ppp_handler_info_t {
ppp_handler_info info;
uint8 _reserved_[_PPP_INFO_T_SIZE_ - sizeof(ppp_handler_info)];
} ppp_handler_info_t;
typedef struct ppp_option_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;
#endif #endif
+7 -3
View File
@@ -12,7 +12,7 @@
// various constants // various constants
#define PPP_HANDLER_NAME_LENGTH_LIMIT 255 #define PPP_HANDLER_NAME_LENGTH_LIMIT 63
// if the name is longer than this value it will be truncated // if the name is longer than this value it will be truncated
// settings keys // settings keys
@@ -66,13 +66,17 @@ enum {
enum { enum {
PPP_NO_FLAGS = 0x00, PPP_NO_FLAGS = 0x00,
PPP_ALWAYS_ALLOWED = 0x01, PPP_ALWAYS_ALLOWED = 0x01,
// protocol may send/receive in PPP_ESTABLISHMENT_PHASE // protocol may send/receive in Phase() >= PPP_ESTABLISHMENT_PHASE,
// but only LCP is allowed in State() != PPP_OPENED_STATE!
PPP_NEEDS_DOWN = 0x02, PPP_NEEDS_DOWN = 0x02,
// protocol needs a Down() in addition to a Reset() to // protocol needs a Down() in addition to a Reset() to
// terminate the connection properly (losing the connection // terminate the connection properly (losing the connection
// still results in a Reset() only) // still results in a Reset() only)
PPP_NOT_IMPORTANT = 0x03 PPP_NOT_IMPORTANT = 0x04,
// if this protocol fails to go up we do not disconnect // if this protocol fails to go up we do not disconnect
PPP_INCLUDES_NCP = 0x08
// This protocol includes the corresponding NCP protocol (e.g.: IPCP + IP).
// All protocol values will also be checked against Protocol() & 0x7FFF.
}; };
// phase when the protocol is brought up // phase when the protocol is brought up
@@ -25,11 +25,11 @@ enum PPP_REPORT_FLAGS {
}; };
// report types // report types
// the first 16 report types are reserved for the interface manager
enum PPP_REPORT_TYPE { enum PPP_REPORT_TYPE {
PPP_DESTRUCTION_REPORT = 0, PPP_DESTRUCTION_REPORT = 16,
// the interface is being destroyed (no code is needed) // the interface is being destroyed (no code is needed)
PPP_CONNECTION_REPORT = 1, PPP_CONNECTION_REPORT = 17
PPP_AUTHENTICATION_REPORT = 2
}; };
// report codes (type-specific) // report codes (type-specific)
@@ -107,6 +107,36 @@ PPPConfigurePacket::ItemAt(int32 index) const
} }
bool
PPPConfigurePacket::HasItemWithType(uint8 type) const
{
ppp_configure_item *item;
for(int32 index; index < CountItems(); index++) {
item = ItemAt(index);
if(item && item->type == type)
return true;
}
return false;
}
ppp_configure_item*
PPPConfigurePacket::ItemWithType(uint8 type) const
{
ppp_configure_item *item;
for(int32 index; index < CountItems(); index++) {
item = ItemAt(index);
if(item && item->type == type)
return item;
}
return NULL;
}
struct mbuf* struct mbuf*
PPPConfigurePacket::ToMbuf(uint32 reserve = 0) PPPConfigurePacket::ToMbuf(uint32 reserve = 0)
{ {
+37 -49
View File
@@ -10,36 +10,33 @@
#include <net/if.h> #include <net/if.h>
#include <mbuf.h> #include <mbuf.h>
#include <PPPControl.h>
PPPDevice::PPPDevice(const char *name, uint32 overhead, PPPInterface *interface,
PPPDevice::PPPDevice(const char *name, PPPInterface& interface,
driver_parameter *settings) driver_parameter *settings)
: fOverhead(overhead), fInterface(interface), : fInterface(interface), fSettings(settings), fMTU(1500)
fSettings(settings)
{ {
if(name) { if(name) {
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0; fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0;
} else } else
strcpy(fName, ""); strcpy(fName, "???");
SetMTU(1500); interface.SetDevice(this);
if(interface)
interface->SetDevice(this);
} }
PPPDevice::~PPPDevice() PPPDevice::~PPPDevice()
{ {
if(Interface()) Interface().SetDevice(NULL);
Interface()->SetDevice(NULL);
} }
status_t status_t
PPPDevice::InitCheck() const PPPDevice::InitCheck() const
{ {
if(!Interface() || !Settings()) if(!Settings())
return B_ERROR; return B_ERROR;
return B_OK; return B_OK;
@@ -50,37 +47,43 @@ status_t
PPPDevice::Control(uint32 op, void *data, size_t length) PPPDevice::Control(uint32 op, void *data, size_t length)
{ {
switch(op) { switch(op) {
// TODO: case PPPC_GET_DEVICE_INFO: {
// get: if(length < sizeof(ppp_device_info_t) || !data)
// - name return B_NO_MEMORY;
// - mtu (+ preferred)
// - status ppp_device_info *info = (ppp_device_info*) data;
// - transfer rates memset(info, 0, sizeof(ppp_device_info_t));
strcpy(info->name, Name());
info->settings = Settings();
info->MTU = MTU();
info->preferredMTU = PreferredMTU();
info->inputTransferRate = InputTransferRate();
info->outputTransferRate = OutputTransferRate();
info->outputBytesCount = CountOutputBytes();
} break;
case PPPC_SET_MTU:
if(length < sizeof(uint32) || !data)
return B_ERROR;
return SetMTU(*((uint32*)data)) ? B_OK : B_ERROR;
break;
default: default:
return B_ERROR; return PPP_UNHANDLED;
} }
return B_OK; return B_OK;
} }
bool
PPPDevice::SetMTU(uint32 MTU)
{
fMTU = MTU;
return true;
}
status_t status_t
PPPDevice::PassToInterface(struct mbuf *packet) PPPDevice::PassToInterface(struct mbuf *packet)
{ {
if(!Interface() || !Interface()->InQueue()) if(!Interface().InQueue())
return B_ERROR; return B_ERROR;
IFQ_ENQUEUE(Interface()->InQueue(), packet); IFQ_ENQUEUE(Interface().InQueue(), packet);
return B_OK; return B_OK;
} }
@@ -96,20 +99,14 @@ PPPDevice::Pulse()
bool bool
PPPDevice::UpStarted() const PPPDevice::UpStarted() const
{ {
if(!Interface()) return Interface().StateMachine().TLSNotify();
return false;
return Interface()->StateMachine().TLSNotify();
} }
bool bool
PPPDevice::DownStarted() const PPPDevice::DownStarted() const
{ {
if(!Interface()) return Interface().StateMachine().TLFNotify();
return false;
return Interface()->StateMachine().TLFNotify();
} }
@@ -118,10 +115,7 @@ PPPDevice::UpFailedEvent()
{ {
fIsUp = false; fIsUp = false;
if(!Interface()) Interface().StateMachine().UpFailedEvent();
return;
Interface()->StateMachine().UpFailedEvent();
} }
@@ -130,10 +124,7 @@ PPPDevice::UpEvent()
{ {
fIsUp = true; fIsUp = true;
if(!Interface()) Interface().StateMachine().UpEvent();
return;
Interface()->StateMachine().UpEvent();
} }
@@ -142,8 +133,5 @@ PPPDevice::DownEvent()
{ {
fIsUp = false; fIsUp = false;
if(!Interface()) Interface().StateMachine().DownEvent();
return;
Interface()->StateMachine().DownEvent();
} }
+50 -37
View File
@@ -6,12 +6,15 @@
//--------------------------------------------------------------------- //---------------------------------------------------------------------
#include <KPPPEncapsulator.h> #include <KPPPEncapsulator.h>
#include <KPPPUtils.h>
#include <PPPControl.h>
PPPEncapsulator::PPPEncapsulator(const char *name, PPP_PHASE phase, PPPEncapsulator::PPPEncapsulator(const char *name, PPP_PHASE phase,
PPP_ENCAPSULATION_LEVEL level, uint16 protocol, PPP_ENCAPSULATION_LEVEL level, uint16 protocol,
int32 addressFamily, uint32 overhead, int32 addressFamily, uint32 overhead,
PPPInterface *interface, driver_parameter *settings, PPPInterface& interface, driver_parameter *settings,
int32 flags = PPP_NO_FLAGS) int32 flags = PPP_NO_FLAGS)
: fOverhead(overhead), fPhase(phase), fLevel(level), fProtocol(protocol), : fOverhead(overhead), fPhase(phase), fLevel(level), fProtocol(protocol),
fAddressFamily(addressFamily), fInterface(interface), fAddressFamily(addressFamily), fInterface(interface),
@@ -22,24 +25,22 @@ PPPEncapsulator::PPPEncapsulator(const char *name, PPP_PHASE phase,
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0; fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0;
} else } else
strcpy(fName, ""); strcpy(fName, "???");
if(interface) interface.AddEncapsulator(this);
interface->AddEncapsulator(this);
} }
PPPEncapsulator::~PPPEncapsulator() PPPEncapsulator::~PPPEncapsulator()
{ {
if(Interface()) Interface().RemoveEncapsulator(this);
Interface()->RemoveEncapsulator(this);
} }
status_t status_t
PPPEncapsulator::InitCheck() const PPPEncapsulator::InitCheck() const
{ {
if(!Interface() || !Settings()) if(!Settings())
return B_ERROR; return B_ERROR;
return B_OK; return B_OK;
@@ -51,13 +52,10 @@ PPPEncapsulator::SetEnabled(bool enabled = true)
{ {
fEnabled = enabled; fEnabled = enabled;
if(!Interface())
return;
if(!enabled) { if(!enabled) {
if(IsUp() || IsGoingUp()) if(IsUp() || IsGoingUp())
Down(); Down();
} else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface()->IsUp()) } else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface().IsUp())
Up(); Up();
} }
@@ -66,16 +64,34 @@ status_t
PPPEncapsulator::Control(uint32 op, void *data, size_t length) PPPEncapsulator::Control(uint32 op, void *data, size_t length)
{ {
switch(op) { switch(op) {
// TODO: case PPPC_GET_HANDLER_INFO: {
// get: if(length < sizeof(ppp_handler_info_t) || !data)
// - name return B_ERROR;
// - level, protocol, address family, overhead
// - status (Is(Going)Up/Down/UpRequested/Enabled) ppp_handler_info *info = (ppp_handler_info*) data;
// set: memset(info, 0, sizeof(ppp_handler_info_t));
// - enabled strcpy(info->name, Name());
info->settings = Settings();
info->phase = Phase();
info->addressFamily = AddressFamily();
info->flags = Flags();
info->protocol = Protocol();
info->isEnabled = IsEnabled();
info->isUpRequested = IsUpRequested();
info->connectionStatus = fConnectionStatus;
info->level = Level();
info->overhead = Overhead();
} break;
case PPPC_SET_ENABLED:
if(length < sizeof(uint32) || !data)
return B_ERROR;
SetEnabled(*((uint32*)data));
break;
default: default:
return B_ERROR; return PPP_UNHANDLED;
} }
return B_OK; return B_OK;
@@ -85,12 +101,18 @@ PPPEncapsulator::Control(uint32 op, void *data, size_t length)
status_t status_t
PPPEncapsulator::SendToNext(struct mbuf *packet, uint16 protocol) const PPPEncapsulator::SendToNext(struct mbuf *packet, uint16 protocol) const
{ {
if(Next()) // Find the next possible handler for this packet.
return Next()->Send(packet, protocol); // This handler should be:
else if(Interface()) // - enabled
return Interface()->SendToDevice(packet, protocol); // - allowed to send
else if(Next()) {
return B_ERROR; if(Next()->IsEnabled()
&& is_handler_allowed(*Next(), Interface().State(), Interface().Phase()))
return Next()->Send(packet, protocol);
else
return Next()->SendToNext(packet, protocol);
} else
return Interface().SendToDevice(packet, protocol);
} }
@@ -120,10 +142,7 @@ PPPEncapsulator::UpFailedEvent()
{ {
fConnectionStatus = PPP_DOWN_PHASE; fConnectionStatus = PPP_DOWN_PHASE;
if(!Interface()) Interface().StateMachine().UpFailedEvent(this);
return;
Interface()->StateMachine().UpFailedEvent(this);
} }
@@ -132,10 +151,7 @@ PPPEncapsulator::UpEvent()
{ {
fConnectionStatus = PPP_ESTABLISHED_PHASE; fConnectionStatus = PPP_ESTABLISHED_PHASE;
if(!Interface()) Interface().StateMachine().UpEvent(this);
return;
Interface()->StateMachine().UpEvent(this);
} }
@@ -144,8 +160,5 @@ PPPEncapsulator::DownEvent()
{ {
fConnectionStatus = PPP_DOWN_PHASE; fConnectionStatus = PPP_DOWN_PHASE;
if(!Interface()) Interface().StateMachine().DownEvent(this);
return;
Interface()->StateMachine().DownEvent(this);
} }
+367 -138
View File
@@ -5,7 +5,7 @@
// Copyright (c) 2003 Waldemar Kornewald, [email protected] // Copyright (c) 2003 Waldemar Kornewald, [email protected]
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Stdio.h must be included before PPPModule.h/PPPManager.h because // stdio.h must be included before PPPModule.h/PPPManager.h because
// dprintf is defined twice with different return values, once with // dprintf is defined twice with different return values, once with
// void (KernelExport.h) and once with int (stdio.h). // void (KernelExport.h) and once with int (stdio.h).
#include <cstdio> #include <cstdio>
@@ -16,8 +16,10 @@
#include <KPPPInterface.h> #include <KPPPInterface.h>
// our other classes // our other classes
#include <PPPControl.h>
#include <KPPPDevice.h> #include <KPPPDevice.h>
#include <KPPPEncapsulator.h> #include <KPPPEncapsulator.h>
#include <KPPPOptionHandler.h>
#include <KPPPModule.h> #include <KPPPModule.h>
#include <KPPPManager.h> #include <KPPPManager.h>
#include <KPPPUtils.h> #include <KPPPUtils.h>
@@ -40,10 +42,11 @@ typedef struct redial_info {
thread_id *thread; thread_id *thread;
} redial_info; } redial_info;
status_t redial_func(void *data); status_t redial_thread(void *data);
// other functions // other functions
status_t in_queue_thread(void *data); status_t in_queue_thread(void *data);
status_t interface_deleter_thread(void *data);
PPPInterface::PPPInterface(uint32 ID, driver_settings *settings, PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
@@ -51,12 +54,12 @@ PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
: fID(ID), fSettings(dup_driver_settings(settings)), : fID(ID), fSettings(dup_driver_settings(settings)),
fStateMachine(*this), fLCP(*this), fReportManager(StateMachine().Locker()), fStateMachine(*this), fLCP(*this), fReportManager(StateMachine().Locker()),
fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0), fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0),
fDialRetriesLimit(0), fIdleSince(0), fLinkMTU(1500), fDevice(NULL), fDialRetriesLimit(0), fIdleSince(0), fMRU(1500), fDevice(NULL),
fFirstEncapsulator(NULL), fLock(StateMachine().Locker()) fFirstEncapsulator(NULL), fLock(StateMachine().Locker()), fDeleteCounter(0)
{ {
// set up queue // set up queue
fInQueue = start_ifq(); fInQueue = start_ifq();
fInQueueThread = spawn_thread(in_queue_thread, "PPPInterface: Input", fInQueueThread = spawn_thread(in_queue_thread, "PPPInterface: in_queue_thread",
B_NORMAL_PRIORITY, this); B_NORMAL_PRIORITY, this);
resume_thread(fInQueueThread); resume_thread(fInQueueThread);
@@ -124,9 +127,23 @@ PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
PPPInterface::~PPPInterface() PPPInterface::~PPPInterface()
{ {
if(fLock.Lock() != B_OK) ++fDeleteCounter;
return;;
// make sure no thread wants to call Unlock() on fLock after it is deleted // make sure we are not accessible by any thread before we continue
UnregisterInterface();
if(fManager)
fManager->remove_interface(ID());
// Call Down() until we get a lock on an interface that is down.
// This lock is not released until we are actually deleted.
while(true) {
Down();
fLock.Lock();
if(State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE)
break;
fLock.Unlock();
}
Report(PPP_DESTRUCTION_REPORT, 0, NULL, 0); Report(PPP_DESTRUCTION_REPORT, 0, NULL, 0);
// tell all listeners that we are being destroyed // tell all listeners that we are being destroyed
@@ -135,13 +152,10 @@ PPPInterface::~PPPInterface()
stop_ifq(InQueue()); stop_ifq(InQueue());
wait_for_thread(fInQueueThread, &tmp); wait_for_thread(fInQueueThread, &tmp);
Down();
UnregisterInterface();
wait_for_thread(fRedialThread, &tmp); wait_for_thread(fRedialThread, &tmp);
while(CountChildren()) while(CountChildren())
ChildAt(0)->Delete(); delete ChildAt(0);
delete Device(); delete Device();
@@ -156,16 +170,34 @@ PPPInterface::~PPPInterface()
free(fModules.ItemAt(index)); free(fModules.ItemAt(index));
} }
put_module(PPP_MANAGER_MODULE_NAME);
free_driver_settings(fSettings); free_driver_settings(fSettings);
if(Parent())
Parent()->RemoveChild(this);
if(fManager)
put_module(PPP_MANAGER_MODULE_NAME);
} }
void void
PPPInterface::Delete() PPPInterface::Delete()
{ {
fManager->delete_interface(ID()); if(atomic_add(&fDeleteCounter, 1) > 0)
return;
// only one thread should delete us!
if(fManager)
fManager->delete_interface(ID());
// This will mark us for deletion.
// Any subsequent calls to delete_interface() will do nothing.
else {
// We were not created by the manager.
// Spawn a thread that will delete us.
thread_id interfaceDeleterThread = spawn_thread(interface_deleter_thread,
"PPPInterface: interface_deleter_thread", B_NORMAL_PRIORITY, this);
resume_thread(interfaceDeleterThread);
}
} }
@@ -187,13 +219,13 @@ PPPInterface::InitCheck() const
void void
PPPInterface::SetLinkMTU(uint32 linkMTU) PPPInterface::SetMRU(uint32 MRU)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
fLinkMTU = linkMTU; fMRU = MRU;
CalculateMRU(); CalculateInterfaceMTU();
} }
@@ -201,16 +233,124 @@ status_t
PPPInterface::Control(uint32 op, void *data, size_t length) PPPInterface::Control(uint32 op, void *data, size_t length)
{ {
switch(op) { switch(op) {
// TODO: case PPPC_GET_INTERFACE_INFO: {
// add: if(length < sizeof(ppp_interface_info_t) || !data)
// - routing Control() to encapsulators/protocols/option_handlers return B_NO_MEMORY;
// (calling their Control() method)
// - adding modules
// - setting AutoRedial and DialOnDemand
ppp_interface_info *info = (ppp_interface_info*) data;
memset(info, 0, sizeof(ppp_interface_info_t));
info->settings = Settings();
info->mode = Mode();
info->state = State();
info->phase = Phase();
info->authenticationStatus = StateMachine().AuthenticationStatus();
info->peerAuthenticationStatus =
StateMachine().PeerAuthenticationStatus();
info->protocolsCount = CountProtocols();
info->encapsulatorsCount = CountEncapsulators();
info->optionHandlersCount = LCP().CountOptionHandlers();
info->LCPExtensionsCount = 0;
info->childrenCount = CountChildren();
info->MRU = MRU();
info->interfaceMTU = InterfaceMTU();
info->idleSince = IdleSince();
info->disconnectAfterIdleSince = DisconnectAfterIdleSince();
info->doesDialOnDemand = DoesDialOnDemand();
info->doesAutoRedial = DoesAutoRedial();
info->hasDevice = Device();
info->isMultilink = IsMultilink();
info->hasParent = Parent();
} break;
case PPPC_SET_MRU:
if(length < sizeof(uint32) || !data)
return B_ERROR;
SetMRU(*((uint32*)data));
break;
case PPPC_SET_DIAL_ON_DEMAND:
if(length < sizeof(uint32) || !data)
return B_NO_MEMORY;
SetDialOnDemand(*((uint32*)data));
break;
case PPPC_SET_AUTO_REDIAL:
if(length < sizeof(uint32) || !data)
return B_NO_MEMORY;
SetAutoRedial(*((uint32*)data));
break;
case PPPC_CONTROL_DEVICE: {
if(length < sizeof(ppp_control_info) || !data)
return B_ERROR;
ppp_control_info *control = (ppp_control_info*) data;
if(control->index != 0 || !Device())
return B_BAD_INDEX;
return Device()->Control(control->op, control->data, control->length);
} break;
case PPPC_CONTROL_PROTOCOL: {
if(length < sizeof(ppp_control_info) || !data)
return B_ERROR;
ppp_control_info *control = (ppp_control_info*) data;
PPPProtocol *protocol_handler = ProtocolAt(control->index);
if(!protocol_handler)
return B_BAD_INDEX;
return protocol_handler->Control(control->op, control->data,
control->length);
} break;
case PPPC_CONTROL_ENCAPSULATOR: {
if(length < sizeof(ppp_control_info) || !data)
return B_ERROR;
ppp_control_info *control = (ppp_control_info*) data;
PPPEncapsulator *encapsulator_handler = EncapsulatorAt(control->index);
if(!encapsulator_handler)
return B_BAD_INDEX;
return encapsulator_handler->Control(control->op, control->data,
control->length);
} break;
case PPPC_CONTROL_OPTION_HANDLER: {
if(length < sizeof(ppp_control_info) || !data)
return B_ERROR;
ppp_control_info *control = (ppp_control_info*) data;
PPPOptionHandler *option_handler = LCP().OptionHandlerAt(control->index);
if(!option_handler)
return B_BAD_INDEX;
return option_handler->Control(control->op, control->data,
control->length);
} break;
case PPPC_CONTROL_LCP_EXTENSION: {
return PPP_UNHANDLED;
} break;
case PPPC_CONTROL_CHILD: {
if(length < sizeof(ppp_control_info) || !data)
return B_ERROR;
ppp_control_info *control = (ppp_control_info*) data;
PPPInterface *child = ChildAt(control->index);
if(!child)
return B_BAD_INDEX;
return child->Control(control->op, control->data, control->length);
} break;
default: default:
return B_ERROR; return PPP_UNHANDLED;
} }
return B_OK; return B_OK;
@@ -238,9 +378,9 @@ PPPInterface::SetDevice(PPPDevice *device)
fDevice = device; fDevice = device;
fLinkMTU = fDevice->MTU(); fMRU = fDevice->MTU();
CalculateMRU(); CalculateInterfaceMTU();
CalculateBaudRate(); CalculateBaudRate();
return true; return true;
@@ -300,14 +440,28 @@ PPPInterface::ProtocolAt(int32 index) const
PPPProtocol* PPPProtocol*
PPPInterface::ProtocolFor(uint16 protocol, int32 start = 0) const PPPInterface::ProtocolFor(uint16 protocol, int32 *start = NULL) const
{ {
if(start < 0) // The iteration style in this method is strange C/C++.
// Explanation: I use this style because it makes extending ProtocolFor
// and EncapsulatorFor simpler as that they look very similar, now.
int32 index = start ? *start : 0;
if(index < 0)
return NULL; return NULL;
for(int32 i = start; i < fProtocols.CountItems(); i++) PPPProtocol *current = ProtocolAt(index);
if(fProtocols.ItemAt(i)->Protocol() == protocol)
return fProtocols.ItemAt(i); for(; current; current = ProtocolAt(++index)) {
if(current->Protocol() == protocol
|| (current->Flags() & PPP_INCLUDES_NCP
&& current->Protocol() & 0x7FFF == protocol & 0x7FFF)) {
if(start)
*start = index;
return current;
}
}
return NULL; return NULL;
} }
@@ -354,7 +508,7 @@ PPPInterface::AddEncapsulator(PPPEncapsulator *encapsulator)
previous->SetNext(encapsulator); previous->SetNext(encapsulator);
} }
CalculateMRU(); CalculateInterfaceMTU();
if(IsUp()) if(IsUp())
encapsulator->Up(); encapsulator->Up();
@@ -386,7 +540,7 @@ PPPInterface::RemoveEncapsulator(PPPEncapsulator *encapsulator)
current->SetNext(NULL); current->SetNext(NULL);
CalculateMRU(); CalculateInterfaceMTU();
return true; return true;
} }
@@ -399,15 +553,42 @@ PPPInterface::RemoveEncapsulator(PPPEncapsulator *encapsulator)
} }
int32
PPPInterface::CountEncapsulators() const
{
PPPEncapsulator *encapsulator = FirstEncapsulator();
int32 count = 0;
for(; encapsulator; encapsulator = encapsulator->Next())
++count;
return count;
}
PPPEncapsulator* PPPEncapsulator*
PPPInterface::EncapsulatorFor(uint16 protocol, PPPInterface::EncapsulatorAt(int32 index) const
PPPEncapsulator *start = NULL) const {
PPPEncapsulator *encapsulator = FirstEncapsulator();
int32 currentIndex = 0;
for(; encapsulator; encapsulator = encapsulator->Next(), ++currentIndex)
if(currentIndex == index)
return encapsulator;
return NULL;
}
PPPEncapsulator*
PPPInterface::EncapsulatorFor(uint16 protocol, PPPEncapsulator *start = NULL) const
{ {
PPPEncapsulator *current = start ? start : fFirstEncapsulator; PPPEncapsulator *current = start ? start : fFirstEncapsulator;
for(; current; current = current->Next()) for(; current; current = current->Next()) {
if(current->Protocol() == protocol) if(current->Protocol() == protocol
|| (current->Flags() & PPP_INCLUDES_NCP
&& current->Protocol() & 0x7FFF == protocol & 0x7FFF))
return current; return current;
}
return current; return current;
} }
@@ -442,7 +623,7 @@ PPPInterface::RemoveChild(PPPInterface *child)
// parents cannot exist without their children // parents cannot exist without their children
if(CountChildren() == 0 && fManager && Ifnet()) if(CountChildren() == 0 && fManager && Ifnet())
fManager->delete_interface(ID()); Delete();
return true; return true;
} }
@@ -495,7 +676,7 @@ PPPInterface::SetDialOnDemand(bool dialondemand = true)
bool bool
PPPInterface::Up() PPPInterface::Up()
{ {
if(!InitCheck() || Phase() == PPP_TERMINATION_PHASE) if(InitCheck() != B_OK || Phase() == PPP_TERMINATION_PHASE)
return false; return false;
if(IsUp()) if(IsUp())
@@ -504,8 +685,11 @@ PPPInterface::Up()
ppp_report_packet report; ppp_report_packet report;
thread_id me = find_thread(NULL), sender; thread_id me = find_thread(NULL), sender;
// one thread has to do the real task while all other threads are observers // One thread has to do the real task while all other threads are observers.
fLock.Lock(); // Lock needs timeout because destructor could have locked the interface.
while(!fLock.LockWithTimeout(100000) != B_NO_ERROR)
if(fDeleteCounter > 0)
return false;
if(fUpThread == -1) if(fUpThread == -1)
fUpThread = me; fUpThread = me;
@@ -518,15 +702,19 @@ PPPInterface::Up()
while(true) { while(true) {
if(IsUp()) { if(IsUp()) {
ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); // lock needs timeout because destructor could have locked the interface
while(!fLock.LockWithTimeout(100000) != B_NO_ERROR)
if(fDeleteCounter > 0)
return true;
if(me == fUpThread) { if(me == fUpThread) {
fLock.Lock();
fDialRetry = 0; fDialRetry = 0;
fUpThread = -1; fUpThread = -1;
fLock.Unlock();
} }
ReportManager().DisableReports(PPP_CONNECTION_REPORT, me);
fLock.Unlock();
return true; return true;
} }
@@ -578,7 +766,7 @@ PPPInterface::Up()
fUpThread = -1; fUpThread = -1;
if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL) if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL)
fManager->delete_interface(ID()); Delete();
} }
PPP_REPLY(sender, B_OK); PPP_REPLY(sender, B_OK);
@@ -616,7 +804,7 @@ PPPInterface::Up()
if(!DoesDialOnDemand() if(!DoesDialOnDemand()
&& report.code != PPP_REPORT_DOWN_SUCCESSFUL) && report.code != PPP_REPORT_DOWN_SUCCESSFUL)
fManager->delete_interface(ID()); Delete();
PPP_REPLY(sender, B_OK); PPP_REPLY(sender, B_OK);
ReportManager().DisableReports(PPP_CONNECTION_REPORT, me); ReportManager().DisableReports(PPP_CONNECTION_REPORT, me);
@@ -643,7 +831,7 @@ PPPInterface::Up()
if(!DoesDialOnDemand() if(!DoesDialOnDemand()
&& report.code != PPP_REPORT_DOWN_SUCCESSFUL) && report.code != PPP_REPORT_DOWN_SUCCESSFUL)
fManager->delete_interface(ID()); Delete();
return false; return false;
} }
@@ -661,7 +849,7 @@ PPPInterface::Up()
bool bool
PPPInterface::Down() PPPInterface::Down()
{ {
if(!InitCheck()) if(InitCheck() != B_OK)
return false; return false;
// this locked section guarantees that there are no state changes before we // this locked section guarantees that there are no state changes before we
@@ -682,6 +870,12 @@ PPPInterface::Down()
if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE) if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE)
continue; continue;
if(report.type == PPP_DESTRUCTION_REPORT)
return true;
if(report.type != PPP_CONNECTION_REPORT)
continue;
if(report.code == PPP_REPORT_DOWN_SUCCESSFUL if(report.code == PPP_REPORT_DOWN_SUCCESSFUL
|| report.code == PPP_REPORT_UP_ABORTED || report.code == PPP_REPORT_UP_ABORTED
|| (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE)) { || (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE)) {
@@ -691,7 +885,7 @@ PPPInterface::Down()
} }
if(!DoesDialOnDemand()) if(!DoesDialOnDemand())
fManager->delete_interface(ID()); Delete();
return true; return true;
} }
@@ -713,18 +907,18 @@ PPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count)
return false; return false;
// a running connection may not change // a running connection may not change
int32 type; PPP_MODULE_KEY_TYPE type;
// which type key was used for loading this module? // which type key was used for loading this module?
const char *name = NULL; const char *name = NULL;
// multilink handling // multilink handling
for(int32 i = start; for(int32 index = start;
i < settings->parameter_count && i < start + count; i++) { index < settings->parameter_count && index < start + count; index++) {
if(!strcasecmp(settings->parameters[i].name, PPP_MULTILINK_KEY) if(!strcasecmp(settings->parameters[index].name, PPP_MULTILINK_KEY)
&& settings->parameters[i].value_count > 0) { && settings->parameters[index].value_count > 0) {
if(!LoadModule(settings->parameters[i].values[0], if(!LoadModule(settings->parameters[index].values[0],
settings->parameters[i].parameters, PPP_MULTILINK_TYPE)) settings->parameters[index].parameters, PPP_MULTILINK_TYPE))
return false; return false;
break; break;
} }
@@ -739,11 +933,11 @@ PPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count)
return true; return true;
} }
for(int32 i = start; for(int32 index = start;
i < settings->parameter_count && i < start + count; i++) { index < settings->parameter_count && index < start + count; index++) {
type = -1; type = PPP_UNDEFINED_KEY_TYPE;
name = settings->parameters[i].name; name = settings->parameters[index].name;
if(!strcasecmp(name, PPP_LOAD_MODULE_KEY)) if(!strcasecmp(name, PPP_LOAD_MODULE_KEY))
type = PPP_LOAD_MODULE_TYPE; type = PPP_LOAD_MODULE_TYPE;
@@ -757,10 +951,10 @@ PPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count)
type = PPP_PEER_AUTHENTICATOR_TYPE; type = PPP_PEER_AUTHENTICATOR_TYPE;
if(type >= 0) if(type >= 0)
for(int32 value_id = 0; value_id < settings->parameters[i].value_count; for(int32 value_id = 0; value_id < settings->parameters[index].value_count;
value_id++) value_id++)
if(!LoadModule(settings->parameters[i].values[value_id], if(!LoadModule(settings->parameters[index].values[value_id],
settings->parameters[i].parameters, type)) settings->parameters[index].parameters, type))
return false; return false;
} }
@@ -770,7 +964,7 @@ PPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count)
bool bool
PPPInterface::LoadModule(const char *name, driver_parameter *parameter, PPPInterface::LoadModule(const char *name, driver_parameter *parameter,
int32 type) PPP_MODULE_KEY_TYPE type)
{ {
if(Phase() != PPP_DOWN_PHASE) if(Phase() != PPP_DOWN_PHASE)
return false; return false;
@@ -791,7 +985,7 @@ PPPInterface::LoadModule(const char *name, driver_parameter *parameter,
// for putting them on our destruction // for putting them on our destruction
fModules.AddItem(module_name); fModules.AddItem(module_name);
return module->add_to(Parent()?Parent():this, this, parameter, type); return module->add_to(Parent()?*Parent():*this, this, parameter, type);
} }
@@ -817,16 +1011,37 @@ PPPInterface::Send(struct mbuf *packet, uint16 protocol)
if(DoesDialOnDemand() && Phase() == PPP_DOWN_PHASE) if(DoesDialOnDemand() && Phase() == PPP_DOWN_PHASE)
Up(); Up();
// If this protocol is always allowed we should send the packet. // find the protocol handler for the current protocol number
// Note that these protocols are not passed to encapsulators! int32 index = 0;
PPPProtocol *sending_protocol = ProtocolFor(protocol); PPPProtocol *sending_protocol = ProtocolFor(protocol, &index);
while(sending_protocol && !sending_protocol->IsEnabled())
sending_protocol = ProtocolFor(protocol, &(++index));
// Check if we must encapsulate the packet.
// We do not necessarily need a handler for 'protocol'.
// In such a case we still encapsulate the packet.
// Protocols which have the PPP_ALWAYS_ALLOWED flag set are never
// encapsulated.
if(sending_protocol && sending_protocol->Flags() & PPP_ALWAYS_ALLOWED if(sending_protocol && sending_protocol->Flags() & PPP_ALWAYS_ALLOWED
&& sending_protocol->IsEnabled() && fDevice->IsUp()) { && is_handler_allowed(*sending_protocol, State(), Phase())) {
fIdleSince = system_time(); fIdleSince = system_time();
return SendToDevice(packet, protocol); return SendToDevice(packet, protocol);
} }
// never send normal protocols when we are down // try the same for the encapsulator handler
PPPEncapsulator *sending_encapsulator = EncapsulatorFor(protocol);
while(sending_encapsulator && sending_encapsulator->Next()
&& !sending_encapsulator->IsEnabled())
sending_encapsulator = sending_encapsulator->Next() ?
EncapsulatorFor(protocol, sending_encapsulator->Next()) : NULL;
if(sending_encapsulator && sending_encapsulator->Flags() & PPP_ALWAYS_ALLOWED
&& is_handler_allowed(*sending_encapsulator, State(), Phase())) {
fIdleSince = system_time();
return SendToDevice(packet, protocol);
}
// never send normal protocols when we are not up
if(!IsUp()) { if(!IsUp()) {
m_freem(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
@@ -841,7 +1056,11 @@ PPPInterface::Send(struct mbuf *packet, uint16 protocol)
if(!fFirstEncapsulator->IsEnabled()) if(!fFirstEncapsulator->IsEnabled())
return fFirstEncapsulator->SendToNext(packet, protocol); return fFirstEncapsulator->SendToNext(packet, protocol);
return fFirstEncapsulator->Send(packet, protocol); if(is_handler_allowed(*fFirstEncapsulator, State(), Phase()))
return fFirstEncapsulator->Send(packet, protocol);
m_freem(packet);
return B_ERROR;
} }
@@ -854,43 +1073,42 @@ PPPInterface::Receive(struct mbuf *packet, uint16 protocol)
int32 result = PPP_REJECTED; int32 result = PPP_REJECTED;
// assume we have no handler // assume we have no handler
// Set our interface as the receiver.
// The real netstack protocols (IP, IPX, etc.) might get confused if our
// interface is a main interface and at the same time is not registered
// because then there is no receiver interface.
// PPP NCPs should be aware of that!
if(packet->m_flags & M_PKTHDR && Ifnet() != NULL)
packet->m_pkthdr.rcvif = Ifnet();
// Find handler and let it parse the packet. // Find handler and let it parse the packet.
// The handler does need not be up because if we are a server // The handler does need not be up because if we are a server
// the handler might be upped by this packet. // the handler might be upped by this packet.
PPPEncapsulator *encapsulator_handler = EncapsulatorFor(protocol); PPPEncapsulator *encapsulator_handler = EncapsulatorFor(protocol);
for(; encapsulator_handler; for(; encapsulator_handler;
encapsulator_handler = EncapsulatorFor(protocol, encapsulator_handler->Next())) { encapsulator_handler =
if(!encapsulator_handler->IsEnabled()) { encapsulator_handler->Next() ?
if(!encapsulator_handler->Next()) EncapsulatorFor(protocol, encapsulator_handler->Next()) : NULL) {
break; if(!encapsulator_handler->IsEnabled()
|| !is_handler_allowed(*encapsulator_handler, State(), Phase()))
continue; continue;
// disabled handlers should not be used // skip handler if disabled or not allowed
}
result = encapsulator_handler->Receive(packet, protocol); result = encapsulator_handler->Receive(packet, protocol);
if(result == PPP_UNHANDLED) { if(result == PPP_UNHANDLED)
if(!encapsulator_handler->Next())
break;
continue; continue;
}
return result; return result;
} }
// no encapsulator handler could be found; try a protocol handler // no encapsulator handler could be found; try a protocol handler
PPPProtocol *protocol_handler; int32 index = 0;
for(int32 index = 0; index < CountProtocols(); index++) { PPPProtocol *protocol_handler = ProtocolFor(protocol, &index);
protocol_handler = ProtocolAt(index); for(; protocol_handler; protocol_handler = ProtocolFor(protocol, &(++index))) {
if(protocol != protocol_handler->Protocol()) if(!protocol_handler->IsEnabled()
|| !is_handler_allowed(*protocol_handler, State(), Phase()))
continue; continue;
// skip handler if disabled or not allowed
if(!protocol_handler->IsEnabled()) {
// disabled handlers should not be used
result = PPP_REJECTED;
continue;
}
result = protocol_handler->Receive(packet, protocol); result = protocol_handler->Receive(packet, protocol);
if(result == PPP_UNHANDLED) if(result == PPP_UNHANDLED)
@@ -899,7 +1117,7 @@ PPPInterface::Receive(struct mbuf *packet, uint16 protocol)
return result; return result;
} }
// maybe the parent interface can handle it // maybe the parent interface can handle the packet
if(Parent()) if(Parent())
return Parent()->Receive(packet, protocol); return Parent()->Receive(packet, protocol);
@@ -920,9 +1138,9 @@ PPPInterface::SendToDevice(struct mbuf *packet, uint16 protocol)
return B_ERROR; return B_ERROR;
// we must pass the basic tests like: // we must pass the basic tests like:
// do we have a device (as main interface)? // do we have a device?
// did we load all modules? // did we load all modules?
if(InitCheck() != B_OK) { if(InitCheck() != B_OK || !Device()) {
m_freem(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
@@ -934,21 +1152,23 @@ PPPInterface::SendToDevice(struct mbuf *packet, uint16 protocol)
} }
// go up if DialOnDemand enabled and we are down // go up if DialOnDemand enabled and we are down
if(DoesDialOnDemand() && (Phase() == PPP_DOWN_PHASE if(DoesDialOnDemand()
|| Phase() == PPP_ESTABLISHMENT_PHASE)) && (Phase() == PPP_DOWN_PHASE
Up(); || Phase() == PPP_ESTABLISHMENT_PHASE)
// Up() waits until it is done && !Up()) {
m_freem(packet);
return B_ERROR;
}
// check if protocol is allowed and everything is up // find the protocol handler for the current protocol number
PPPProtocol *sending_protocol = ProtocolFor(protocol); int32 index = 0;
if(!fDevice->IsUp() PPPProtocol *sending_protocol = ProtocolFor(protocol, &index);
|| (!IsUp() && protocol != PPP_LCP_PROTOCOL while(sending_protocol && !sending_protocol->IsEnabled())
&& (!sending_protocol sending_protocol = ProtocolFor(protocol, &(++index));
|| sending_protocol->Flags() & PPP_ALWAYS_ALLOWED == 0
|| !sending_protocol->IsEnabled() // make sure that protocol is allowed to send and everything is up
) if(!Device()->IsUp() || !sending_protocol || !sending_protocol->IsEnabled()
) || !is_handler_allowed(*sending_protocol, State(), Phase())){
) {
m_freem(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
@@ -969,8 +1189,8 @@ PPPInterface::SendToDevice(struct mbuf *packet, uint16 protocol)
// pass to device/children // pass to device/children
if(!IsMultilink() || Parent()) { if(!IsMultilink() || Parent()) {
// check if packet is too big for device // check if packet is too big for device
if((packet->m_flags & M_PKTHDR && (uint32) packet->m_pkthdr.len > LinkMTU()) if((packet->m_flags & M_PKTHDR && (uint32) packet->m_pkthdr.len > MRU())
|| packet->m_len > LinkMTU()) { || packet->m_len > MRU()) {
m_freem(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
@@ -990,7 +1210,7 @@ PPPInterface::ReceiveFromDevice(struct mbuf *packet)
if(!packet) if(!packet)
return B_ERROR; return B_ERROR;
if(!InitCheck()) { if(InitCheck() != B_OK) {
m_freem(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
@@ -999,14 +1219,7 @@ PPPInterface::ReceiveFromDevice(struct mbuf *packet)
uint16 *protocol = mtod(packet, uint16*); uint16 *protocol = mtod(packet, uint16*);
*protocol = ntohs(*protocol); *protocol = ntohs(*protocol);
m_adj(packet, sizeof(uint16)); m_adj(packet, 2);
// Set our interface as the receiver.
// This might be NULL, so protocols that belong to the network stack (IP, etc.)
// will probably be confused (as there is no interface from which the packet came).
// Protocols that live only in the PPP interface should have no problems with this.
if(packet->m_flags & M_PKTHDR)
packet->m_pkthdr.rcvif = Ifnet();
return Receive(packet, *protocol); return Receive(packet, *protocol);
} }
@@ -1015,6 +1228,10 @@ PPPInterface::ReceiveFromDevice(struct mbuf *packet)
void void
PPPInterface::Pulse() PPPInterface::Pulse()
{ {
if(fDeleteCounter > 0)
return;
// we have no pulse when we are dead ;)
// check our idle time and disconnect if needed // check our idle time and disconnect if needed
if(fDisconnectAfterIdleSince > 0 && fIdleSince != 0 if(fDisconnectAfterIdleSince > 0 && fIdleSince != 0
&& fIdleSince - system_time() >= fDisconnectAfterIdleSince) { && fIdleSince - system_time() >= fDisconnectAfterIdleSince) {
@@ -1041,7 +1258,7 @@ PPPInterface::RegisterInterface()
return true; return true;
// we are already registered // we are already registered
if(!InitCheck()) if(InitCheck() != B_OK)
return false; return false;
// we cannot register if something is wrong // we cannot register if something is wrong
@@ -1085,9 +1302,9 @@ PPPInterface::UnregisterInterface()
void void
PPPInterface::CalculateMRU() PPPInterface::CalculateInterfaceMTU()
{ {
fMRU = fLinkMTU; fInterfaceMTU = fMRU;
// sum all headers // sum all headers
fHeaderLength = sizeof(uint16); fHeaderLength = sizeof(uint16);
@@ -1096,15 +1313,15 @@ PPPInterface::CalculateMRU()
for(; encapsulator; encapsulator = encapsulator->Next()) for(; encapsulator; encapsulator = encapsulator->Next())
fHeaderLength += encapsulator->Overhead(); fHeaderLength += encapsulator->Overhead();
fMRU -= fHeaderLength; fInterfaceMTU -= fHeaderLength;
if(Ifnet()) { if(Ifnet()) {
Ifnet()->if_mtu = fMRU; Ifnet()->if_mtu = fInterfaceMTU;
Ifnet()->if_hdrlen = fHeaderLength; Ifnet()->if_hdrlen = fHeaderLength;
} }
if(Parent()) if(Parent())
Parent()->CalculateMRU(); Parent()->CalculateInterfaceMTU();
} }
@@ -1133,26 +1350,29 @@ PPPInterface::Redial()
return; return;
// start a new thread that calls our Up() method // start a new thread that calls our Up() method
redial_info *info = new redial_info; redial_info info;
info->interface = this; info.interface = this;
info->thread = &fRedialThread; info.thread = &fRedialThread;
fRedialThread = spawn_thread(redial_func, "PPPInterface: redial_thread", fRedialThread = spawn_thread(redial_thread, "PPPInterface: redial_thread",
B_NORMAL_PRIORITY, info); B_NORMAL_PRIORITY, NULL);
resume_thread(fRedialThread); resume_thread(fRedialThread);
send_data(fRedialThread, 0, &info, sizeof(redial_info));
} }
status_t status_t
redial_func(void *data) redial_thread(void *data)
{ {
redial_info *info = (redial_info*) data; redial_info info;
thread_id sender;
info->interface->Up(); receive_data(&sender, &info, sizeof(redial_info));
*info->thread = -1;
delete info; info.interface->Up();
*info.thread = -1;
return B_OK; return B_OK;
} }
@@ -1182,3 +1402,12 @@ in_queue_thread(void *data)
return B_ERROR; return B_ERROR;
} }
status_t
interface_deleter_thread(void *data)
{
delete (PPPInterface*) data;
return B_OK;
}
+3 -7
View File
@@ -25,7 +25,7 @@
PPPLCP::PPPLCP(PPPInterface& interface) PPPLCP::PPPLCP(PPPInterface& interface)
: PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL, : PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL,
AF_UNSPEC, &interface, NULL, PPP_ALWAYS_ALLOWED), AF_UNSPEC, interface, NULL, PPP_ALWAYS_ALLOWED),
fStateMachine(interface.StateMachine()), fTarget(NULL) fStateMachine(interface.StateMachine()), fTarget(NULL)
{ {
SetUpRequested(false); SetUpRequested(false);
@@ -87,8 +87,6 @@ PPPLCP::AdditionalOverhead() const
if(Target()) if(Target())
overhead += Target()->Overhead(); overhead += Target()->Overhead();
if(Interface()->Device())
overhead += Interface()->Device()->Overhead();
return overhead; return overhead;
} }
@@ -113,10 +111,8 @@ PPPLCP::Send(struct mbuf *packet)
{ {
if(Target()) if(Target())
return Target()->Send(packet, PPP_LCP_PROTOCOL); return Target()->Send(packet, PPP_LCP_PROTOCOL);
else if(Interface())
return Interface()->Send(packet, PPP_LCP_PROTOCOL);
else else
return B_ERROR; return Interface().Send(packet, PPP_LCP_PROTOCOL);
} }
@@ -171,7 +167,7 @@ PPPLCP::Receive(struct mbuf *packet, uint16 protocol)
break; break;
default: default:
return B_ERROR; StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT);
} }
return B_OK; return B_OK;
@@ -7,8 +7,10 @@
#include <KPPPOptionHandler.h> #include <KPPPOptionHandler.h>
#include <PPPControl.h>
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)
{ {
@@ -16,25 +18,53 @@ PPPOptionHandler::PPPOptionHandler(const char *name, PPPInterface *interface,
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0; fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0;
} else } else
strcpy(fName, ""); strcpy(fName, "???");
if(interface) interface.LCP().AddOptionHandler(this);
interface->LCP().AddOptionHandler(this);
} }
PPPOptionHandler::~PPPOptionHandler() PPPOptionHandler::~PPPOptionHandler()
{ {
if(Interface()) Interface().LCP().RemoveOptionHandler(this);
Interface()->LCP().RemoveOptionHandler(this);
} }
status_t status_t
PPPOptionHandler::InitCheck() const PPPOptionHandler::InitCheck() const
{ {
if(!Interface() || !Settings()) if(!Settings())
return B_ERROR; return B_ERROR;
return B_OK; return B_OK;
} }
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)
return B_ERROR;
ppp_option_handler_info *info = (ppp_option_handler_info*) data;
memset(info, 0, sizeof(ppp_option_handler_info));
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;
}
+35 -31
View File
@@ -7,11 +7,13 @@
#include <KPPPInterface.h> #include <KPPPInterface.h>
#include <PPPControl.h>
#include <cstring> #include <cstring>
PPPProtocol::PPPProtocol(const char *name, PPP_PHASE phase, uint16 protocol, PPPProtocol::PPPProtocol(const char *name, PPP_PHASE phase, uint16 protocol,
int32 addressFamily, PPPInterface *interface, int32 addressFamily, PPPInterface& interface,
driver_parameter *settings, int32 flags = PPP_NO_FLAGS) driver_parameter *settings, int32 flags = PPP_NO_FLAGS)
: fPhase(phase), fProtocol(protocol), fAddressFamily(addressFamily), : fPhase(phase), fProtocol(protocol), fAddressFamily(addressFamily),
fInterface(interface), fSettings(settings), fFlags(flags), fInterface(interface), fSettings(settings), fFlags(flags),
@@ -21,24 +23,22 @@ PPPProtocol::PPPProtocol(const char *name, PPP_PHASE phase, uint16 protocol,
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT); strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0; fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0;
} else } else
strcpy(fName, ""); strcpy(fName, "???");
if(interface) interface.AddProtocol(this);
interface->AddProtocol(this);
} }
PPPProtocol::~PPPProtocol() PPPProtocol::~PPPProtocol()
{ {
if(Interface()) Interface().RemoveProtocol(this);
Interface()->RemoveProtocol(this);
} }
status_t status_t
PPPProtocol::InitCheck() const PPPProtocol::InitCheck() const
{ {
if(!Interface() || !Settings()) if(!Settings())
return B_ERROR; return B_ERROR;
return B_OK; return B_OK;
@@ -50,13 +50,10 @@ PPPProtocol::SetEnabled(bool enabled = true)
{ {
fEnabled = enabled; fEnabled = enabled;
if(!Interface())
return;
if(!enabled) { if(!enabled) {
if(IsUp() || IsGoingUp()) if(IsUp() || IsGoingUp())
Down(); Down();
} else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface()->IsUp()) } else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface().IsUp())
Up(); Up();
} }
@@ -65,16 +62,32 @@ status_t
PPPProtocol::Control(uint32 op, void *data, size_t length) PPPProtocol::Control(uint32 op, void *data, size_t length)
{ {
switch(op) { switch(op) {
// TODO: case PPPC_GET_HANDLER_INFO: {
// get: if(length < sizeof(ppp_handler_info_t) || !data)
// - name return B_ERROR;
// - protocol, address family
// - status (Is(Going)Up/Down/UpRequested/Enabled) ppp_handler_info *info = (ppp_handler_info*) data;
// set: memset(info, 0, sizeof(ppp_handler_info_t));
// - enabled strcpy(info->name, Name());
info->settings = Settings();
info->phase = Phase();
info->addressFamily = AddressFamily();
info->flags = Flags();
info->protocol = Protocol();
info->isEnabled = IsEnabled();
info->isUpRequested = IsUpRequested();
info->connectionStatus = fConnectionStatus;
} break;
case PPPC_SET_ENABLED:
if(length < sizeof(uint32) || !data)
return B_ERROR;
SetEnabled(*((uint32*)data));
break;
default: default:
return B_ERROR; return PPP_UNHANDLED;
} }
return B_OK; return B_OK;
@@ -107,10 +120,7 @@ PPPProtocol::UpFailedEvent()
{ {
fConnectionStatus = PPP_DOWN_PHASE; fConnectionStatus = PPP_DOWN_PHASE;
if(!Interface()) Interface().StateMachine().UpFailedEvent(this);
return;
Interface()->StateMachine().UpFailedEvent(this);
} }
@@ -119,10 +129,7 @@ PPPProtocol::UpEvent()
{ {
fConnectionStatus = PPP_ESTABLISHED_PHASE; fConnectionStatus = PPP_ESTABLISHED_PHASE;
if(!Interface()) Interface().StateMachine().UpEvent(this);
return;
Interface()->StateMachine().UpEvent(this);
} }
@@ -131,8 +138,5 @@ PPPProtocol::DownEvent()
{ {
fConnectionStatus = PPP_DOWN_PHASE; fConnectionStatus = PPP_DOWN_PHASE;
if(!Interface()) Interface().StateMachine().DownEvent(this);
return;
Interface()->StateMachine().DownEvent(this);
} }
+16 -16
View File
@@ -185,12 +185,12 @@ PPPStateMachine::UpEvent(PPPInterface *interface)
if(Phase() == PPP_ESTABLISHMENT_PHASE) { if(Phase() == PPP_ESTABLISHMENT_PHASE) {
// this is the first interface that went up // this is the first interface that went up
Interface()->SetLinkMTU(interface->LinkMTU()); Interface()->SetMRU(interface->MRU());
locker.UnlockNow(); locker.UnlockNow();
ThisLayerUp(); ThisLayerUp();
} else if(Interface()->LinkMTU() > interface->LinkMTU()) } else if(Interface()->MRU() > interface->MRU())
Interface()->SetLinkMTU(interface->LinkMTU()); Interface()->SetMRU(interface->MRU());
// linkMTU should always be the smallest value of all children // MRU should always be the smallest value of all children
NewState(PPP_OPENED_STATE); NewState(PPP_OPENED_STATE);
} }
@@ -201,8 +201,8 @@ PPPStateMachine::DownEvent(PPPInterface *interface)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
uint32 linkMTU = 0; uint32 MRU = 0;
// the new linkMTU // the new MRU
Interface()->CalculateBaudRate(); Interface()->CalculateBaudRate();
@@ -214,17 +214,17 @@ PPPStateMachine::DownEvent(PPPInterface *interface)
child = Interface()->ChildAt(index); child = Interface()->ChildAt(index);
if(child && child->IsUp()) { if(child && child->IsUp()) {
// set linkMTU to the smallest value of all children // set MRU to the smallest value of all children
if(linkMTU == 0) if(MRU == 0)
linkMTU = child->LinkMTU(); MRU = child->MRU();
else if(linkMTU > child->LinkMTU()) else if(MRU > child->MRU())
linkMTU = child->LinkMTU(); MRU = child->MRU();
++count; ++count;
} }
} }
Interface()->SetLinkMTU(linkMTU); Interface()->SetMRU(MRU);
if(count == 0) { if(count == 0) {
locker.UnlockNow(); locker.UnlockNow();
@@ -1463,10 +1463,10 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type
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) {
if((uint32) packet->m_pkthdr.len > Interface()->LinkMTU()) if((uint32) packet->m_pkthdr.len > Interface()->MRU())
adjust = Interface()->LinkMTU() - packet->m_pkthdr.len; adjust = Interface()->MRU() - packet->m_pkthdr.len;
} else if(packet->m_len > Interface()->LinkMTU()) } else if(packet->m_len > Interface()->MRU())
adjust = Interface()->LinkMTU() - packet->m_len; adjust = Interface()->MRU() - packet->m_len;
if(adjust != 0) if(adjust != 0)
m_adj(packet, adjust); m_adj(packet, adjust);