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:
parent
8d1a0ee7c1
commit
a602502a7e
@ -45,6 +45,8 @@ class PPPConfigurePacket {
|
||||
int32 CountItems() const
|
||||
{ return fItems.CountItems(); }
|
||||
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);
|
||||
// the user is responsible for freeing the mbuf
|
||||
|
@ -18,8 +18,9 @@ typedef uint32 interface_id;
|
||||
|
||||
|
||||
// module key types (used when loading a module)
|
||||
enum {
|
||||
PPP_LOAD_MODULE_TYPE,
|
||||
enum PPP_MODULE_KEY_TYPE {
|
||||
PPP_UNDEFINED_KEY_TYPE = -1,
|
||||
PPP_LOAD_MODULE_TYPE = 0,
|
||||
PPP_DEVICE_TYPE,
|
||||
PPP_PROTOCOL_TYPE,
|
||||
PPP_AUTHENTICATOR_TYPE,
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
class PPPDevice {
|
||||
public:
|
||||
PPPDevice(const char *name, uint32 overhead, PPPInterface *interface,
|
||||
PPPDevice(const char *name, PPPInterface& interface,
|
||||
driver_parameter *settings);
|
||||
virtual ~PPPDevice();
|
||||
|
||||
@ -28,10 +28,7 @@ class PPPDevice {
|
||||
const char *Name() const
|
||||
{ return fName; }
|
||||
|
||||
uint32 Overhead() const
|
||||
{ return fOverhead; }
|
||||
|
||||
PPPInterface *Interface() const
|
||||
PPPInterface& Interface() const
|
||||
{ return fInterface; }
|
||||
driver_parameter *Settings() const
|
||||
{ return fSettings; }
|
||||
@ -85,8 +82,7 @@ class PPPDevice {
|
||||
|
||||
private:
|
||||
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
|
||||
uint32 fOverhead;
|
||||
PPPInterface *fInterface;
|
||||
PPPInterface& fInterface;
|
||||
driver_parameter *fSettings;
|
||||
|
||||
uint32 fMTU;
|
||||
|
@ -24,7 +24,7 @@ class PPPEncapsulator {
|
||||
PPPEncapsulator(const char *name, PPP_PHASE phase,
|
||||
PPP_ENCAPSULATION_LEVEL level, uint16 protocol,
|
||||
int32 addressFamily, uint32 overhead,
|
||||
PPPInterface *interface, driver_parameter *settings,
|
||||
PPPInterface& interface, driver_parameter *settings,
|
||||
int32 flags = PPP_NO_FLAGS);
|
||||
virtual ~PPPEncapsulator();
|
||||
|
||||
@ -41,7 +41,7 @@ class PPPEncapsulator {
|
||||
uint32 Overhead() const
|
||||
{ return fOverhead; }
|
||||
|
||||
PPPInterface *Interface() const
|
||||
PPPInterface& Interface() const
|
||||
{ return fInterface; }
|
||||
driver_parameter *Settings() const
|
||||
{ return fSettings; }
|
||||
@ -58,8 +58,6 @@ class PPPEncapsulator {
|
||||
bool IsEnabled() const
|
||||
{ return fEnabled; }
|
||||
|
||||
void SetUpRequested(bool requested = true)
|
||||
{ fUpRequested = requested; }
|
||||
bool IsUpRequested() const
|
||||
{ return fUpRequested; }
|
||||
|
||||
@ -92,6 +90,9 @@ class PPPEncapsulator {
|
||||
virtual void Pulse();
|
||||
|
||||
protected:
|
||||
void SetUpRequested(bool requested = true)
|
||||
{ fUpRequested = requested; }
|
||||
|
||||
void UpStarted();
|
||||
void DownStarted();
|
||||
|
||||
@ -109,7 +110,7 @@ class PPPEncapsulator {
|
||||
PPP_ENCAPSULATION_LEVEL fLevel;
|
||||
uint16 fProtocol;
|
||||
int32 fAddressFamily;
|
||||
PPPInterface *fInterface;
|
||||
PPPInterface& fInterface;
|
||||
driver_parameter *fSettings;
|
||||
int32 fFlags;
|
||||
|
||||
|
@ -74,12 +74,13 @@ class PPPInterface {
|
||||
bigtime_t DisconnectAfterIdleSince() const
|
||||
{ return fDisconnectAfterIdleSince; }
|
||||
|
||||
void SetLinkMTU(uint32 linkMTU);
|
||||
uint32 LinkMTU() const
|
||||
{ return fLinkMTU; }
|
||||
// this is the smallest MTU that we and the peer have
|
||||
void SetMRU(uint32 MRU);
|
||||
uint32 MRU() const
|
||||
{ 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);
|
||||
|
||||
@ -92,12 +93,14 @@ class PPPInterface {
|
||||
int32 CountProtocols() const
|
||||
{ return fProtocols.CountItems(); }
|
||||
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
|
||||
{ return fProtocols.IndexOf(protocol); }
|
||||
|
||||
bool AddEncapsulator(PPPEncapsulator *encapsulator);
|
||||
bool RemoveEncapsulator(PPPEncapsulator *encapsulator);
|
||||
int32 CountEncapsulators() const;
|
||||
PPPEncapsulator *EncapsulatorAt(int32 index) const;
|
||||
PPPEncapsulator *FirstEncapsulator() const
|
||||
{ return fFirstEncapsulator; }
|
||||
PPPEncapsulator *EncapsulatorFor(uint16 protocol,
|
||||
@ -144,7 +147,7 @@ class PPPInterface {
|
||||
bool LoadModules(driver_settings *settings,
|
||||
int32 start, int32 count);
|
||||
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 Receive(struct mbuf *packet, uint16 protocol);
|
||||
@ -164,7 +167,7 @@ class PPPInterface {
|
||||
// saves the returned ifnet structure
|
||||
bool UnregisterInterface();
|
||||
|
||||
void CalculateMRU();
|
||||
void CalculateInterfaceMTU();
|
||||
void CalculateBaudRate();
|
||||
|
||||
void Redial();
|
||||
@ -191,7 +194,7 @@ class PPPInterface {
|
||||
ppp_manager_info *fManager;
|
||||
|
||||
bigtime_t fIdleSince, fDisconnectAfterIdleSince;
|
||||
uint32 fLinkMTU, fMRU, fHeaderLength;
|
||||
uint32 fMRU, fInterfaceMTU, fHeaderLength;
|
||||
|
||||
PPPInterface *fParent;
|
||||
List<PPPInterface*> fChildren;
|
||||
@ -211,6 +214,7 @@ class PPPInterface {
|
||||
BLocker& fLock;
|
||||
|
||||
status_t fInitStatus;
|
||||
int32 fDeleteCounter;
|
||||
};
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@ typedef struct ppp_manager_info {
|
||||
// you should always create interfaces using this function
|
||||
void (*delete_interface)(interface_id ID);
|
||||
// this marks the interface for deletion
|
||||
void (*remove_interface)(interface_id ID);
|
||||
|
||||
ifnet* (*register_interface)(interface_id ID);
|
||||
bool (*unregister_interface)(interface_id ID);
|
||||
|
@ -16,11 +16,12 @@ class PPPInterface;
|
||||
typedef struct ppp_module_info {
|
||||
module_info minfo;
|
||||
status_t (*control)(uint32 op, void *data, size_t length);
|
||||
status_t (*add_to)(PPPInterface *mainInterface, PPPInterface *subInterface,
|
||||
driver_parameter *settings, int32 type);
|
||||
status_t (*add_to)(PPPInterface& mainInterface, PPPInterface *subInterface,
|
||||
driver_parameter *settings, PPP_MODULE_KEY_TYPE type);
|
||||
// multilink: handlers that must run on a real device
|
||||
// should be added to subInterface while mainInterface
|
||||
// handlers are used for the bundle of interfaces
|
||||
// should be added to subInterface (may be NULL)
|
||||
// while mainInterface handlers are used for the
|
||||
// bundle of interfaces
|
||||
} ppp_module_info;
|
||||
|
||||
|
||||
|
@ -21,23 +21,25 @@ class PPPConfigurePacket;
|
||||
|
||||
class PPPOptionHandler {
|
||||
public:
|
||||
PPPOptionHandler(const char *name, PPPInterface *interface,
|
||||
PPPOptionHandler(const char *name, PPPInterface& interface,
|
||||
driver_parameter *settings);
|
||||
virtual ~PPPOptionHandler();
|
||||
|
||||
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);
|
||||
bool IsEnabled() const
|
||||
{ return fEnabled; }
|
||||
|
||||
const char *Name() const
|
||||
{ return fName; }
|
||||
|
||||
PPPInterface *Interface() const
|
||||
{ return fInterface; }
|
||||
driver_parameter *Settings() const
|
||||
{ return fSettings; }
|
||||
virtual status_t Control(uint32 op, void *data, size_t length);
|
||||
|
||||
virtual void Reset() = 0;
|
||||
// e.g.: remove list of rejected values
|
||||
@ -61,7 +63,7 @@ class PPPOptionHandler {
|
||||
|
||||
private:
|
||||
char fName[PPP_HANDLER_NAME_LENGTH_LIMIT + 1];
|
||||
PPPInterface *fInterface;
|
||||
PPPInterface& fInterface;
|
||||
driver_parameter *fSettings;
|
||||
|
||||
bool fEnabled;
|
||||
|
@ -18,7 +18,7 @@ class PPPInterface;
|
||||
class PPPProtocol {
|
||||
public:
|
||||
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);
|
||||
virtual ~PPPProtocol();
|
||||
|
||||
@ -30,7 +30,7 @@ class PPPProtocol {
|
||||
PPP_PHASE Phase() const
|
||||
{ return fPhase; }
|
||||
|
||||
PPPInterface *Interface() const
|
||||
PPPInterface& Interface() const
|
||||
{ return fInterface; }
|
||||
driver_parameter *Settings() const
|
||||
{ return fSettings; }
|
||||
@ -47,8 +47,6 @@ class PPPProtocol {
|
||||
bool IsEnabled() const
|
||||
{ return fEnabled; }
|
||||
|
||||
void SetUpRequested(bool requested = true)
|
||||
{ fUpRequested = requested; }
|
||||
bool IsUpRequested() const
|
||||
{ return fUpRequested; }
|
||||
|
||||
@ -71,6 +69,9 @@ class PPPProtocol {
|
||||
virtual void Pulse();
|
||||
|
||||
protected:
|
||||
void SetUpRequested(bool requested = true)
|
||||
{ fUpRequested = requested; }
|
||||
|
||||
void UpStarted();
|
||||
void DownStarted();
|
||||
|
||||
@ -84,7 +85,7 @@ class PPPProtocol {
|
||||
PPP_PHASE fPhase;
|
||||
uint16 fProtocol;
|
||||
int32 fAddressFamily;
|
||||
PPPInterface *fInterface;
|
||||
PPPInterface& fInterface;
|
||||
driver_parameter *fSettings;
|
||||
int32 fFlags;
|
||||
|
||||
|
@ -8,6 +8,29 @@
|
||||
#ifndef _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
|
||||
// and there is a race condition beween has_data() and send/receive_data().
|
||||
|
@ -31,7 +31,7 @@ class LockerHelper {
|
||||
public:
|
||||
LockerHelper(BLocker& lock) : fLock(&lock)
|
||||
{
|
||||
if(fLock->Lock() != B_OK)
|
||||
if(!fLock->Lock())
|
||||
fLock = NULL;
|
||||
}
|
||||
|
||||
|
@ -15,32 +15,27 @@
|
||||
// starting values and other values for control ops
|
||||
#define PPP_RESERVE_OPS_COUNT 0xFFFF
|
||||
#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_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_OPTION_HANDLER_OPS_START PPP_OPS_START + 5 * PPP_RESERVE_OPS_COUNT
|
||||
#define PPP_LCP_EXTENSION_OPS_START PPP_OPS_START + 6 * PPP_RESERVE_OPS_COUNT
|
||||
#define PPP_COMMON_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
|
||||
|
||||
|
||||
enum PPP_CONTROL_OPS {
|
||||
// -----------------------------------------------------
|
||||
// PPPInterface
|
||||
PPPC_GET_STATUS = PPP_OPS_START,
|
||||
PPPC_GET_MRU,
|
||||
PPPC_GET_INTERFACE_INFO = PPP_INTERFACE_OPS_START,
|
||||
PPPC_SET_MRU,
|
||||
PPPC_GET_LINK_MTU,
|
||||
PPPC_SET_LINK_MTU,
|
||||
PPPC_GET_DIAL_ON_DEMAND,
|
||||
PPPC_SET_DIAL_ON_DEMAND,
|
||||
PPPC_GET_AUTO_REDIAL,
|
||||
PPPC_SET_AUTO_REDIAL,
|
||||
PPPC_GET_PROTOCOLS_COUNT,
|
||||
PPPC_GET_ENCAPSULATORS_COUNT,
|
||||
PPPC_GET_OPTION_HANDLERS_COUNT,
|
||||
PPPC_GET_LCP_EXTENSIONS_COUNT,
|
||||
PPPC_GET_CHILDREN_COUNT,
|
||||
|
||||
// handler access
|
||||
PPPC_CONTROL_DEVICE,
|
||||
PPPC_CONTROL_PROTOCOL,
|
||||
PPPC_CONTROL_ENCAPSULATOR,
|
||||
PPPC_CONTROL_OPTION_HANDLER,
|
||||
@ -50,9 +45,8 @@ enum PPP_CONTROL_OPS {
|
||||
|
||||
// -----------------------------------------------------
|
||||
// PPPDevice
|
||||
PPPC_GET_MTU = PPP_DEVICE_OPS_START,
|
||||
PPPC_GET_DEVICE_INFO = PPP_DEVICE_OPS_START,
|
||||
PPPC_SET_MTU,
|
||||
PPPC_GET_PREFERRED_MTU,
|
||||
// -----------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------
|
||||
@ -65,6 +59,7 @@ enum PPP_CONTROL_OPS {
|
||||
|
||||
// -----------------------------------------------------
|
||||
// PPPOptionHandler
|
||||
PPPC_GET_OPTION_HANDLER_INFO = PPP_OPTION_HANDLER_OPS_START,
|
||||
// -----------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------
|
||||
@ -72,45 +67,116 @@ enum PPP_CONTROL_OPS {
|
||||
// -----------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------
|
||||
// PPPProtocol and PPPEncapsulator
|
||||
PPPC_GET_NAME,
|
||||
PPPC_GET_ENABLED = PPP_COMMON_PROTO_ENCAPS_OPS_START,
|
||||
// Common/mixed ops
|
||||
PPPC_GET_HANDLER_INFO = PPP_COMMON_OPS_START,
|
||||
PPPC_SET_ENABLED,
|
||||
// -----------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------
|
||||
// PPPProtocol and PPPEncapsulator
|
||||
// -----------------------------------------------------
|
||||
|
||||
PPP_CONTROL_OPS_END = B_DEVICE_OP_CODES_END + 0xFFFF
|
||||
};
|
||||
|
||||
|
||||
typedef struct ppp_control_structure {
|
||||
typedef struct ppp_control_info {
|
||||
uint32 index;
|
||||
// index of interface/protocol/encapsulator/etc.
|
||||
uint32 op;
|
||||
// the Control()/ioctl() opcode
|
||||
|
||||
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.
|
||||
|
||||
void *data;
|
||||
size_t length;
|
||||
// not always needed
|
||||
} ppp_control_structure;
|
||||
// should always be set
|
||||
} 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_STATE state;
|
||||
PPP_PHASE phase;
|
||||
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)
|
||||
+ 2 * sizeof(PPP_AUTHENTICATION_STATUS) + sizeof(bigtime_t))];
|
||||
} ppp_status_structure;
|
||||
bigtime_t idleSince, disconnectAfterIdleSince;
|
||||
|
||||
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
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
// settings keys
|
||||
@ -66,13 +66,17 @@ enum {
|
||||
enum {
|
||||
PPP_NO_FLAGS = 0x00,
|
||||
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,
|
||||
// protocol needs a Down() in addition to a Reset() to
|
||||
// terminate the connection properly (losing the connection
|
||||
// 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
|
||||
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
|
||||
|
@ -25,11 +25,11 @@ enum PPP_REPORT_FLAGS {
|
||||
};
|
||||
|
||||
// report types
|
||||
// the first 16 report types are reserved for the interface manager
|
||||
enum PPP_REPORT_TYPE {
|
||||
PPP_DESTRUCTION_REPORT = 0,
|
||||
PPP_DESTRUCTION_REPORT = 16,
|
||||
// the interface is being destroyed (no code is needed)
|
||||
PPP_CONNECTION_REPORT = 1,
|
||||
PPP_AUTHENTICATION_REPORT = 2
|
||||
PPP_CONNECTION_REPORT = 17
|
||||
};
|
||||
|
||||
// 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*
|
||||
PPPConfigurePacket::ToMbuf(uint32 reserve = 0)
|
||||
{
|
||||
|
@ -10,36 +10,33 @@
|
||||
#include <net/if.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)
|
||||
: fOverhead(overhead), fInterface(interface),
|
||||
fSettings(settings)
|
||||
: fInterface(interface), fSettings(settings), fMTU(1500)
|
||||
{
|
||||
if(name) {
|
||||
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
|
||||
fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0;
|
||||
} else
|
||||
strcpy(fName, "");
|
||||
strcpy(fName, "???");
|
||||
|
||||
SetMTU(1500);
|
||||
|
||||
if(interface)
|
||||
interface->SetDevice(this);
|
||||
interface.SetDevice(this);
|
||||
}
|
||||
|
||||
|
||||
PPPDevice::~PPPDevice()
|
||||
{
|
||||
if(Interface())
|
||||
Interface()->SetDevice(NULL);
|
||||
Interface().SetDevice(NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPDevice::InitCheck() const
|
||||
{
|
||||
if(!Interface() || !Settings())
|
||||
if(!Settings())
|
||||
return B_ERROR;
|
||||
|
||||
return B_OK;
|
||||
@ -50,37 +47,43 @@ status_t
|
||||
PPPDevice::Control(uint32 op, void *data, size_t length)
|
||||
{
|
||||
switch(op) {
|
||||
// TODO:
|
||||
// get:
|
||||
// - name
|
||||
// - mtu (+ preferred)
|
||||
// - status
|
||||
// - transfer rates
|
||||
case PPPC_GET_DEVICE_INFO: {
|
||||
if(length < sizeof(ppp_device_info_t) || !data)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
ppp_device_info *info = (ppp_device_info*) data;
|
||||
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:
|
||||
return B_ERROR;
|
||||
return PPP_UNHANDLED;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PPPDevice::SetMTU(uint32 MTU)
|
||||
{
|
||||
fMTU = MTU;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPDevice::PassToInterface(struct mbuf *packet)
|
||||
{
|
||||
if(!Interface() || !Interface()->InQueue())
|
||||
if(!Interface().InQueue())
|
||||
return B_ERROR;
|
||||
|
||||
IFQ_ENQUEUE(Interface()->InQueue(), packet);
|
||||
IFQ_ENQUEUE(Interface().InQueue(), packet);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -96,20 +99,14 @@ PPPDevice::Pulse()
|
||||
bool
|
||||
PPPDevice::UpStarted() const
|
||||
{
|
||||
if(!Interface())
|
||||
return false;
|
||||
|
||||
return Interface()->StateMachine().TLSNotify();
|
||||
return Interface().StateMachine().TLSNotify();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PPPDevice::DownStarted() const
|
||||
{
|
||||
if(!Interface())
|
||||
return false;
|
||||
|
||||
return Interface()->StateMachine().TLFNotify();
|
||||
return Interface().StateMachine().TLFNotify();
|
||||
}
|
||||
|
||||
|
||||
@ -118,10 +115,7 @@ PPPDevice::UpFailedEvent()
|
||||
{
|
||||
fIsUp = false;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
Interface()->StateMachine().UpFailedEvent();
|
||||
Interface().StateMachine().UpFailedEvent();
|
||||
}
|
||||
|
||||
|
||||
@ -130,10 +124,7 @@ PPPDevice::UpEvent()
|
||||
{
|
||||
fIsUp = true;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
Interface()->StateMachine().UpEvent();
|
||||
Interface().StateMachine().UpEvent();
|
||||
}
|
||||
|
||||
|
||||
@ -142,8 +133,5 @@ PPPDevice::DownEvent()
|
||||
{
|
||||
fIsUp = false;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
Interface()->StateMachine().DownEvent();
|
||||
Interface().StateMachine().DownEvent();
|
||||
}
|
||||
|
@ -6,12 +6,15 @@
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <KPPPEncapsulator.h>
|
||||
#include <KPPPUtils.h>
|
||||
|
||||
#include <PPPControl.h>
|
||||
|
||||
|
||||
PPPEncapsulator::PPPEncapsulator(const char *name, PPP_PHASE phase,
|
||||
PPP_ENCAPSULATION_LEVEL level, uint16 protocol,
|
||||
int32 addressFamily, uint32 overhead,
|
||||
PPPInterface *interface, driver_parameter *settings,
|
||||
PPPInterface& interface, driver_parameter *settings,
|
||||
int32 flags = PPP_NO_FLAGS)
|
||||
: fOverhead(overhead), fPhase(phase), fLevel(level), fProtocol(protocol),
|
||||
fAddressFamily(addressFamily), fInterface(interface),
|
||||
@ -22,24 +25,22 @@ PPPEncapsulator::PPPEncapsulator(const char *name, PPP_PHASE phase,
|
||||
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
|
||||
fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0;
|
||||
} else
|
||||
strcpy(fName, "");
|
||||
strcpy(fName, "???");
|
||||
|
||||
if(interface)
|
||||
interface->AddEncapsulator(this);
|
||||
interface.AddEncapsulator(this);
|
||||
}
|
||||
|
||||
|
||||
PPPEncapsulator::~PPPEncapsulator()
|
||||
{
|
||||
if(Interface())
|
||||
Interface()->RemoveEncapsulator(this);
|
||||
Interface().RemoveEncapsulator(this);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPEncapsulator::InitCheck() const
|
||||
{
|
||||
if(!Interface() || !Settings())
|
||||
if(!Settings())
|
||||
return B_ERROR;
|
||||
|
||||
return B_OK;
|
||||
@ -51,13 +52,10 @@ PPPEncapsulator::SetEnabled(bool enabled = true)
|
||||
{
|
||||
fEnabled = enabled;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
if(!enabled) {
|
||||
if(IsUp() || IsGoingUp())
|
||||
Down();
|
||||
} else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface()->IsUp())
|
||||
} else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface().IsUp())
|
||||
Up();
|
||||
}
|
||||
|
||||
@ -66,16 +64,34 @@ status_t
|
||||
PPPEncapsulator::Control(uint32 op, void *data, size_t length)
|
||||
{
|
||||
switch(op) {
|
||||
// TODO:
|
||||
// get:
|
||||
// - name
|
||||
// - level, protocol, address family, overhead
|
||||
// - status (Is(Going)Up/Down/UpRequested/Enabled)
|
||||
// set:
|
||||
// - enabled
|
||||
case PPPC_GET_HANDLER_INFO: {
|
||||
if(length < sizeof(ppp_handler_info_t) || !data)
|
||||
return B_ERROR;
|
||||
|
||||
ppp_handler_info *info = (ppp_handler_info*) data;
|
||||
memset(info, 0, sizeof(ppp_handler_info_t));
|
||||
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:
|
||||
return B_ERROR;
|
||||
return PPP_UNHANDLED;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -85,12 +101,18 @@ PPPEncapsulator::Control(uint32 op, void *data, size_t length)
|
||||
status_t
|
||||
PPPEncapsulator::SendToNext(struct mbuf *packet, uint16 protocol) const
|
||||
{
|
||||
if(Next())
|
||||
return Next()->Send(packet, protocol);
|
||||
else if(Interface())
|
||||
return Interface()->SendToDevice(packet, protocol);
|
||||
else
|
||||
return B_ERROR;
|
||||
// Find the next possible handler for this packet.
|
||||
// This handler should be:
|
||||
// - enabled
|
||||
// - allowed to send
|
||||
if(Next()) {
|
||||
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;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
Interface()->StateMachine().UpFailedEvent(this);
|
||||
Interface().StateMachine().UpFailedEvent(this);
|
||||
}
|
||||
|
||||
|
||||
@ -132,10 +151,7 @@ PPPEncapsulator::UpEvent()
|
||||
{
|
||||
fConnectionStatus = PPP_ESTABLISHED_PHASE;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
Interface()->StateMachine().UpEvent(this);
|
||||
Interface().StateMachine().UpEvent(this);
|
||||
}
|
||||
|
||||
|
||||
@ -144,8 +160,5 @@ PPPEncapsulator::DownEvent()
|
||||
{
|
||||
fConnectionStatus = PPP_DOWN_PHASE;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
Interface()->StateMachine().DownEvent(this);
|
||||
Interface().StateMachine().DownEvent(this);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// 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
|
||||
// void (KernelExport.h) and once with int (stdio.h).
|
||||
#include <cstdio>
|
||||
@ -16,8 +16,10 @@
|
||||
#include <KPPPInterface.h>
|
||||
|
||||
// our other classes
|
||||
#include <PPPControl.h>
|
||||
#include <KPPPDevice.h>
|
||||
#include <KPPPEncapsulator.h>
|
||||
#include <KPPPOptionHandler.h>
|
||||
#include <KPPPModule.h>
|
||||
#include <KPPPManager.h>
|
||||
#include <KPPPUtils.h>
|
||||
@ -40,10 +42,11 @@ typedef struct redial_info {
|
||||
thread_id *thread;
|
||||
} redial_info;
|
||||
|
||||
status_t redial_func(void *data);
|
||||
status_t redial_thread(void *data);
|
||||
|
||||
// other functions
|
||||
status_t in_queue_thread(void *data);
|
||||
status_t interface_deleter_thread(void *data);
|
||||
|
||||
|
||||
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)),
|
||||
fStateMachine(*this), fLCP(*this), fReportManager(StateMachine().Locker()),
|
||||
fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0),
|
||||
fDialRetriesLimit(0), fIdleSince(0), fLinkMTU(1500), fDevice(NULL),
|
||||
fFirstEncapsulator(NULL), fLock(StateMachine().Locker())
|
||||
fDialRetriesLimit(0), fIdleSince(0), fMRU(1500), fDevice(NULL),
|
||||
fFirstEncapsulator(NULL), fLock(StateMachine().Locker()), fDeleteCounter(0)
|
||||
{
|
||||
// set up queue
|
||||
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);
|
||||
resume_thread(fInQueueThread);
|
||||
|
||||
@ -124,9 +127,23 @@ PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
|
||||
|
||||
PPPInterface::~PPPInterface()
|
||||
{
|
||||
if(fLock.Lock() != B_OK)
|
||||
return;;
|
||||
// make sure no thread wants to call Unlock() on fLock after it is deleted
|
||||
++fDeleteCounter;
|
||||
|
||||
// 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);
|
||||
// tell all listeners that we are being destroyed
|
||||
@ -135,13 +152,10 @@ PPPInterface::~PPPInterface()
|
||||
stop_ifq(InQueue());
|
||||
wait_for_thread(fInQueueThread, &tmp);
|
||||
|
||||
Down();
|
||||
UnregisterInterface();
|
||||
|
||||
wait_for_thread(fRedialThread, &tmp);
|
||||
|
||||
while(CountChildren())
|
||||
ChildAt(0)->Delete();
|
||||
delete ChildAt(0);
|
||||
|
||||
delete Device();
|
||||
|
||||
@ -156,16 +170,34 @@ PPPInterface::~PPPInterface()
|
||||
free(fModules.ItemAt(index));
|
||||
}
|
||||
|
||||
put_module(PPP_MANAGER_MODULE_NAME);
|
||||
|
||||
free_driver_settings(fSettings);
|
||||
|
||||
if(Parent())
|
||||
Parent()->RemoveChild(this);
|
||||
|
||||
if(fManager)
|
||||
put_module(PPP_MANAGER_MODULE_NAME);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
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
|
||||
PPPInterface::SetLinkMTU(uint32 linkMTU)
|
||||
PPPInterface::SetMRU(uint32 MRU)
|
||||
{
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
fLinkMTU = linkMTU;
|
||||
fMRU = MRU;
|
||||
|
||||
CalculateMRU();
|
||||
CalculateInterfaceMTU();
|
||||
}
|
||||
|
||||
|
||||
@ -201,16 +233,124 @@ status_t
|
||||
PPPInterface::Control(uint32 op, void *data, size_t length)
|
||||
{
|
||||
switch(op) {
|
||||
// TODO:
|
||||
// add:
|
||||
// - routing Control() to encapsulators/protocols/option_handlers
|
||||
// (calling their Control() method)
|
||||
// - adding modules
|
||||
// - setting AutoRedial and DialOnDemand
|
||||
case PPPC_GET_INTERFACE_INFO: {
|
||||
if(length < sizeof(ppp_interface_info_t) || !data)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
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:
|
||||
return B_ERROR;
|
||||
return PPP_UNHANDLED;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -238,9 +378,9 @@ PPPInterface::SetDevice(PPPDevice *device)
|
||||
|
||||
fDevice = device;
|
||||
|
||||
fLinkMTU = fDevice->MTU();
|
||||
fMRU = fDevice->MTU();
|
||||
|
||||
CalculateMRU();
|
||||
CalculateInterfaceMTU();
|
||||
CalculateBaudRate();
|
||||
|
||||
return true;
|
||||
@ -300,14 +440,28 @@ PPPInterface::ProtocolAt(int32 index) const
|
||||
|
||||
|
||||
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;
|
||||
|
||||
for(int32 i = start; i < fProtocols.CountItems(); i++)
|
||||
if(fProtocols.ItemAt(i)->Protocol() == protocol)
|
||||
return fProtocols.ItemAt(i);
|
||||
PPPProtocol *current = ProtocolAt(index);
|
||||
|
||||
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;
|
||||
}
|
||||
@ -354,7 +508,7 @@ PPPInterface::AddEncapsulator(PPPEncapsulator *encapsulator)
|
||||
previous->SetNext(encapsulator);
|
||||
}
|
||||
|
||||
CalculateMRU();
|
||||
CalculateInterfaceMTU();
|
||||
|
||||
if(IsUp())
|
||||
encapsulator->Up();
|
||||
@ -386,7 +540,7 @@ PPPInterface::RemoveEncapsulator(PPPEncapsulator *encapsulator)
|
||||
|
||||
current->SetNext(NULL);
|
||||
|
||||
CalculateMRU();
|
||||
CalculateInterfaceMTU();
|
||||
|
||||
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*
|
||||
PPPInterface::EncapsulatorFor(uint16 protocol,
|
||||
PPPEncapsulator *start = NULL) const
|
||||
PPPInterface::EncapsulatorAt(int32 index) 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;
|
||||
|
||||
for(; current; current = current->Next())
|
||||
if(current->Protocol() == protocol)
|
||||
for(; current; current = current->Next()) {
|
||||
if(current->Protocol() == protocol
|
||||
|| (current->Flags() & PPP_INCLUDES_NCP
|
||||
&& current->Protocol() & 0x7FFF == protocol & 0x7FFF))
|
||||
return current;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
@ -442,7 +623,7 @@ PPPInterface::RemoveChild(PPPInterface *child)
|
||||
|
||||
// parents cannot exist without their children
|
||||
if(CountChildren() == 0 && fManager && Ifnet())
|
||||
fManager->delete_interface(ID());
|
||||
Delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -495,7 +676,7 @@ PPPInterface::SetDialOnDemand(bool dialondemand = true)
|
||||
bool
|
||||
PPPInterface::Up()
|
||||
{
|
||||
if(!InitCheck() || Phase() == PPP_TERMINATION_PHASE)
|
||||
if(InitCheck() != B_OK || Phase() == PPP_TERMINATION_PHASE)
|
||||
return false;
|
||||
|
||||
if(IsUp())
|
||||
@ -504,8 +685,11 @@ PPPInterface::Up()
|
||||
ppp_report_packet report;
|
||||
thread_id me = find_thread(NULL), sender;
|
||||
|
||||
// one thread has to do the real task while all other threads are observers
|
||||
fLock.Lock();
|
||||
// One thread has to do the real task while all other threads are observers.
|
||||
// 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)
|
||||
fUpThread = me;
|
||||
|
||||
@ -518,15 +702,19 @@ PPPInterface::Up()
|
||||
|
||||
while(true) {
|
||||
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) {
|
||||
fLock.Lock();
|
||||
fDialRetry = 0;
|
||||
fUpThread = -1;
|
||||
fLock.Unlock();
|
||||
}
|
||||
|
||||
ReportManager().DisableReports(PPP_CONNECTION_REPORT, me);
|
||||
fLock.Unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -578,7 +766,7 @@ PPPInterface::Up()
|
||||
fUpThread = -1;
|
||||
|
||||
if(!DoesDialOnDemand() && report.code != PPP_REPORT_DOWN_SUCCESSFUL)
|
||||
fManager->delete_interface(ID());
|
||||
Delete();
|
||||
}
|
||||
|
||||
PPP_REPLY(sender, B_OK);
|
||||
@ -616,7 +804,7 @@ PPPInterface::Up()
|
||||
|
||||
if(!DoesDialOnDemand()
|
||||
&& report.code != PPP_REPORT_DOWN_SUCCESSFUL)
|
||||
fManager->delete_interface(ID());
|
||||
Delete();
|
||||
|
||||
PPP_REPLY(sender, B_OK);
|
||||
ReportManager().DisableReports(PPP_CONNECTION_REPORT, me);
|
||||
@ -643,7 +831,7 @@ PPPInterface::Up()
|
||||
|
||||
if(!DoesDialOnDemand()
|
||||
&& report.code != PPP_REPORT_DOWN_SUCCESSFUL)
|
||||
fManager->delete_interface(ID());
|
||||
Delete();
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -661,7 +849,7 @@ PPPInterface::Up()
|
||||
bool
|
||||
PPPInterface::Down()
|
||||
{
|
||||
if(!InitCheck())
|
||||
if(InitCheck() != B_OK)
|
||||
return false;
|
||||
|
||||
// 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)
|
||||
continue;
|
||||
|
||||
if(report.type == PPP_DESTRUCTION_REPORT)
|
||||
return true;
|
||||
|
||||
if(report.type != PPP_CONNECTION_REPORT)
|
||||
continue;
|
||||
|
||||
if(report.code == PPP_REPORT_DOWN_SUCCESSFUL
|
||||
|| report.code == PPP_REPORT_UP_ABORTED
|
||||
|| (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE)) {
|
||||
@ -691,7 +885,7 @@ PPPInterface::Down()
|
||||
}
|
||||
|
||||
if(!DoesDialOnDemand())
|
||||
fManager->delete_interface(ID());
|
||||
Delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -713,18 +907,18 @@ PPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count)
|
||||
return false;
|
||||
// a running connection may not change
|
||||
|
||||
int32 type;
|
||||
PPP_MODULE_KEY_TYPE type;
|
||||
// which type key was used for loading this module?
|
||||
|
||||
const char *name = NULL;
|
||||
|
||||
// multilink handling
|
||||
for(int32 i = start;
|
||||
i < settings->parameter_count && i < start + count; i++) {
|
||||
if(!strcasecmp(settings->parameters[i].name, PPP_MULTILINK_KEY)
|
||||
&& settings->parameters[i].value_count > 0) {
|
||||
if(!LoadModule(settings->parameters[i].values[0],
|
||||
settings->parameters[i].parameters, PPP_MULTILINK_TYPE))
|
||||
for(int32 index = start;
|
||||
index < settings->parameter_count && index < start + count; index++) {
|
||||
if(!strcasecmp(settings->parameters[index].name, PPP_MULTILINK_KEY)
|
||||
&& settings->parameters[index].value_count > 0) {
|
||||
if(!LoadModule(settings->parameters[index].values[0],
|
||||
settings->parameters[index].parameters, PPP_MULTILINK_TYPE))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@ -739,11 +933,11 @@ PPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count)
|
||||
return true;
|
||||
}
|
||||
|
||||
for(int32 i = start;
|
||||
i < settings->parameter_count && i < start + count; i++) {
|
||||
type = -1;
|
||||
for(int32 index = start;
|
||||
index < settings->parameter_count && index < start + count; index++) {
|
||||
type = PPP_UNDEFINED_KEY_TYPE;
|
||||
|
||||
name = settings->parameters[i].name;
|
||||
name = settings->parameters[index].name;
|
||||
|
||||
if(!strcasecmp(name, PPP_LOAD_MODULE_KEY))
|
||||
type = PPP_LOAD_MODULE_TYPE;
|
||||
@ -757,10 +951,10 @@ PPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count)
|
||||
type = PPP_PEER_AUTHENTICATOR_TYPE;
|
||||
|
||||
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++)
|
||||
if(!LoadModule(settings->parameters[i].values[value_id],
|
||||
settings->parameters[i].parameters, type))
|
||||
if(!LoadModule(settings->parameters[index].values[value_id],
|
||||
settings->parameters[index].parameters, type))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -770,7 +964,7 @@ PPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count)
|
||||
|
||||
bool
|
||||
PPPInterface::LoadModule(const char *name, driver_parameter *parameter,
|
||||
int32 type)
|
||||
PPP_MODULE_KEY_TYPE type)
|
||||
{
|
||||
if(Phase() != PPP_DOWN_PHASE)
|
||||
return false;
|
||||
@ -791,7 +985,7 @@ PPPInterface::LoadModule(const char *name, driver_parameter *parameter,
|
||||
// for putting them on our destruction
|
||||
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)
|
||||
Up();
|
||||
|
||||
// If this protocol is always allowed we should send the packet.
|
||||
// Note that these protocols are not passed to encapsulators!
|
||||
PPPProtocol *sending_protocol = ProtocolFor(protocol);
|
||||
// find the protocol handler for the current protocol number
|
||||
int32 index = 0;
|
||||
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
|
||||
&& sending_protocol->IsEnabled() && fDevice->IsUp()) {
|
||||
&& is_handler_allowed(*sending_protocol, State(), Phase())) {
|
||||
fIdleSince = system_time();
|
||||
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()) {
|
||||
m_freem(packet);
|
||||
return B_ERROR;
|
||||
@ -841,7 +1056,11 @@ PPPInterface::Send(struct mbuf *packet, uint16 protocol)
|
||||
if(!fFirstEncapsulator->IsEnabled())
|
||||
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;
|
||||
// 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.
|
||||
// The handler does need not be up because if we are a server
|
||||
// the handler might be upped by this packet.
|
||||
PPPEncapsulator *encapsulator_handler = EncapsulatorFor(protocol);
|
||||
for(; encapsulator_handler;
|
||||
encapsulator_handler = EncapsulatorFor(protocol, encapsulator_handler->Next())) {
|
||||
if(!encapsulator_handler->IsEnabled()) {
|
||||
if(!encapsulator_handler->Next())
|
||||
break;
|
||||
|
||||
encapsulator_handler =
|
||||
encapsulator_handler->Next() ?
|
||||
EncapsulatorFor(protocol, encapsulator_handler->Next()) : NULL) {
|
||||
if(!encapsulator_handler->IsEnabled()
|
||||
|| !is_handler_allowed(*encapsulator_handler, State(), Phase()))
|
||||
continue;
|
||||
// disabled handlers should not be used
|
||||
}
|
||||
// skip handler if disabled or not allowed
|
||||
|
||||
result = encapsulator_handler->Receive(packet, protocol);
|
||||
if(result == PPP_UNHANDLED) {
|
||||
if(!encapsulator_handler->Next())
|
||||
break;
|
||||
|
||||
if(result == PPP_UNHANDLED)
|
||||
continue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// no encapsulator handler could be found; try a protocol handler
|
||||
PPPProtocol *protocol_handler;
|
||||
for(int32 index = 0; index < CountProtocols(); index++) {
|
||||
protocol_handler = ProtocolAt(index);
|
||||
if(protocol != protocol_handler->Protocol())
|
||||
int32 index = 0;
|
||||
PPPProtocol *protocol_handler = ProtocolFor(protocol, &index);
|
||||
for(; protocol_handler; protocol_handler = ProtocolFor(protocol, &(++index))) {
|
||||
if(!protocol_handler->IsEnabled()
|
||||
|| !is_handler_allowed(*protocol_handler, State(), Phase()))
|
||||
continue;
|
||||
|
||||
if(!protocol_handler->IsEnabled()) {
|
||||
// disabled handlers should not be used
|
||||
result = PPP_REJECTED;
|
||||
continue;
|
||||
}
|
||||
// skip handler if disabled or not allowed
|
||||
|
||||
result = protocol_handler->Receive(packet, protocol);
|
||||
if(result == PPP_UNHANDLED)
|
||||
@ -899,7 +1117,7 @@ PPPInterface::Receive(struct mbuf *packet, uint16 protocol)
|
||||
return result;
|
||||
}
|
||||
|
||||
// maybe the parent interface can handle it
|
||||
// maybe the parent interface can handle the packet
|
||||
if(Parent())
|
||||
return Parent()->Receive(packet, protocol);
|
||||
|
||||
@ -920,9 +1138,9 @@ PPPInterface::SendToDevice(struct mbuf *packet, uint16 protocol)
|
||||
return B_ERROR;
|
||||
|
||||
// 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?
|
||||
if(InitCheck() != B_OK) {
|
||||
if(InitCheck() != B_OK || !Device()) {
|
||||
m_freem(packet);
|
||||
return B_ERROR;
|
||||
}
|
||||
@ -934,21 +1152,23 @@ PPPInterface::SendToDevice(struct mbuf *packet, uint16 protocol)
|
||||
}
|
||||
|
||||
// go up if DialOnDemand enabled and we are down
|
||||
if(DoesDialOnDemand() && (Phase() == PPP_DOWN_PHASE
|
||||
|| Phase() == PPP_ESTABLISHMENT_PHASE))
|
||||
Up();
|
||||
// Up() waits until it is done
|
||||
if(DoesDialOnDemand()
|
||||
&& (Phase() == PPP_DOWN_PHASE
|
||||
|| Phase() == PPP_ESTABLISHMENT_PHASE)
|
||||
&& !Up()) {
|
||||
m_freem(packet);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// check if protocol is allowed and everything is up
|
||||
PPPProtocol *sending_protocol = ProtocolFor(protocol);
|
||||
if(!fDevice->IsUp()
|
||||
|| (!IsUp() && protocol != PPP_LCP_PROTOCOL
|
||||
&& (!sending_protocol
|
||||
|| sending_protocol->Flags() & PPP_ALWAYS_ALLOWED == 0
|
||||
|| !sending_protocol->IsEnabled()
|
||||
)
|
||||
)
|
||||
) {
|
||||
// find the protocol handler for the current protocol number
|
||||
int32 index = 0;
|
||||
PPPProtocol *sending_protocol = ProtocolFor(protocol, &index);
|
||||
while(sending_protocol && !sending_protocol->IsEnabled())
|
||||
sending_protocol = ProtocolFor(protocol, &(++index));
|
||||
|
||||
// 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);
|
||||
return B_ERROR;
|
||||
}
|
||||
@ -969,8 +1189,8 @@ PPPInterface::SendToDevice(struct mbuf *packet, uint16 protocol)
|
||||
// pass to device/children
|
||||
if(!IsMultilink() || Parent()) {
|
||||
// check if packet is too big for device
|
||||
if((packet->m_flags & M_PKTHDR && (uint32) packet->m_pkthdr.len > LinkMTU())
|
||||
|| packet->m_len > LinkMTU()) {
|
||||
if((packet->m_flags & M_PKTHDR && (uint32) packet->m_pkthdr.len > MRU())
|
||||
|| packet->m_len > MRU()) {
|
||||
m_freem(packet);
|
||||
return B_ERROR;
|
||||
}
|
||||
@ -990,7 +1210,7 @@ PPPInterface::ReceiveFromDevice(struct mbuf *packet)
|
||||
if(!packet)
|
||||
return B_ERROR;
|
||||
|
||||
if(!InitCheck()) {
|
||||
if(InitCheck() != B_OK) {
|
||||
m_freem(packet);
|
||||
return B_ERROR;
|
||||
}
|
||||
@ -999,14 +1219,7 @@ PPPInterface::ReceiveFromDevice(struct mbuf *packet)
|
||||
uint16 *protocol = mtod(packet, uint16*);
|
||||
*protocol = ntohs(*protocol);
|
||||
|
||||
m_adj(packet, sizeof(uint16));
|
||||
|
||||
// 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();
|
||||
m_adj(packet, 2);
|
||||
|
||||
return Receive(packet, *protocol);
|
||||
}
|
||||
@ -1015,6 +1228,10 @@ PPPInterface::ReceiveFromDevice(struct mbuf *packet)
|
||||
void
|
||||
PPPInterface::Pulse()
|
||||
{
|
||||
if(fDeleteCounter > 0)
|
||||
return;
|
||||
// we have no pulse when we are dead ;)
|
||||
|
||||
// check our idle time and disconnect if needed
|
||||
if(fDisconnectAfterIdleSince > 0 && fIdleSince != 0
|
||||
&& fIdleSince - system_time() >= fDisconnectAfterIdleSince) {
|
||||
@ -1041,7 +1258,7 @@ PPPInterface::RegisterInterface()
|
||||
return true;
|
||||
// we are already registered
|
||||
|
||||
if(!InitCheck())
|
||||
if(InitCheck() != B_OK)
|
||||
return false;
|
||||
// we cannot register if something is wrong
|
||||
|
||||
@ -1085,9 +1302,9 @@ PPPInterface::UnregisterInterface()
|
||||
|
||||
|
||||
void
|
||||
PPPInterface::CalculateMRU()
|
||||
PPPInterface::CalculateInterfaceMTU()
|
||||
{
|
||||
fMRU = fLinkMTU;
|
||||
fInterfaceMTU = fMRU;
|
||||
|
||||
// sum all headers
|
||||
fHeaderLength = sizeof(uint16);
|
||||
@ -1096,15 +1313,15 @@ PPPInterface::CalculateMRU()
|
||||
for(; encapsulator; encapsulator = encapsulator->Next())
|
||||
fHeaderLength += encapsulator->Overhead();
|
||||
|
||||
fMRU -= fHeaderLength;
|
||||
fInterfaceMTU -= fHeaderLength;
|
||||
|
||||
if(Ifnet()) {
|
||||
Ifnet()->if_mtu = fMRU;
|
||||
Ifnet()->if_mtu = fInterfaceMTU;
|
||||
Ifnet()->if_hdrlen = fHeaderLength;
|
||||
}
|
||||
|
||||
if(Parent())
|
||||
Parent()->CalculateMRU();
|
||||
Parent()->CalculateInterfaceMTU();
|
||||
}
|
||||
|
||||
|
||||
@ -1133,26 +1350,29 @@ PPPInterface::Redial()
|
||||
return;
|
||||
|
||||
// start a new thread that calls our Up() method
|
||||
redial_info *info = new redial_info;
|
||||
info->interface = this;
|
||||
info->thread = &fRedialThread;
|
||||
redial_info info;
|
||||
info.interface = this;
|
||||
info.thread = &fRedialThread;
|
||||
|
||||
fRedialThread = spawn_thread(redial_func, "PPPInterface: redial_thread",
|
||||
B_NORMAL_PRIORITY, info);
|
||||
fRedialThread = spawn_thread(redial_thread, "PPPInterface: redial_thread",
|
||||
B_NORMAL_PRIORITY, NULL);
|
||||
|
||||
resume_thread(fRedialThread);
|
||||
|
||||
send_data(fRedialThread, 0, &info, sizeof(redial_info));
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
*info->thread = -1;
|
||||
receive_data(&sender, &info, sizeof(redial_info));
|
||||
|
||||
delete info;
|
||||
info.interface->Up();
|
||||
*info.thread = -1;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -1182,3 +1402,12 @@ in_queue_thread(void *data)
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
interface_deleter_thread(void *data)
|
||||
{
|
||||
delete (PPPInterface*) data;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
PPPLCP::PPPLCP(PPPInterface& interface)
|
||||
: 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)
|
||||
{
|
||||
SetUpRequested(false);
|
||||
@ -87,8 +87,6 @@ PPPLCP::AdditionalOverhead() const
|
||||
|
||||
if(Target())
|
||||
overhead += Target()->Overhead();
|
||||
if(Interface()->Device())
|
||||
overhead += Interface()->Device()->Overhead();
|
||||
|
||||
return overhead;
|
||||
}
|
||||
@ -113,10 +111,8 @@ PPPLCP::Send(struct mbuf *packet)
|
||||
{
|
||||
if(Target())
|
||||
return Target()->Send(packet, PPP_LCP_PROTOCOL);
|
||||
else if(Interface())
|
||||
return Interface()->Send(packet, PPP_LCP_PROTOCOL);
|
||||
else
|
||||
return B_ERROR;
|
||||
return Interface().Send(packet, PPP_LCP_PROTOCOL);
|
||||
}
|
||||
|
||||
|
||||
@ -171,7 +167,7 @@ PPPLCP::Receive(struct mbuf *packet, uint16 protocol)
|
||||
break;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
@ -7,8 +7,10 @@
|
||||
|
||||
#include <KPPPOptionHandler.h>
|
||||
|
||||
#include <PPPControl.h>
|
||||
|
||||
PPPOptionHandler::PPPOptionHandler(const char *name, PPPInterface *interface,
|
||||
|
||||
PPPOptionHandler::PPPOptionHandler(const char *name, PPPInterface& interface,
|
||||
driver_parameter *settings)
|
||||
: fInterface(interface), fSettings(settings)
|
||||
{
|
||||
@ -16,25 +18,53 @@ PPPOptionHandler::PPPOptionHandler(const char *name, PPPInterface *interface,
|
||||
strncpy(fName, name, PPP_HANDLER_NAME_LENGTH_LIMIT);
|
||||
fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0;
|
||||
} else
|
||||
strcpy(fName, "");
|
||||
strcpy(fName, "???");
|
||||
|
||||
if(interface)
|
||||
interface->LCP().AddOptionHandler(this);
|
||||
interface.LCP().AddOptionHandler(this);
|
||||
}
|
||||
|
||||
|
||||
PPPOptionHandler::~PPPOptionHandler()
|
||||
{
|
||||
if(Interface())
|
||||
Interface()->LCP().RemoveOptionHandler(this);
|
||||
Interface().LCP().RemoveOptionHandler(this);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPOptionHandler::InitCheck() const
|
||||
{
|
||||
if(!Interface() || !Settings())
|
||||
if(!Settings())
|
||||
return B_ERROR;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -7,11 +7,13 @@
|
||||
|
||||
#include <KPPPInterface.h>
|
||||
|
||||
#include <PPPControl.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
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)
|
||||
: fPhase(phase), fProtocol(protocol), fAddressFamily(addressFamily),
|
||||
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);
|
||||
fName[PPP_HANDLER_NAME_LENGTH_LIMIT] = 0;
|
||||
} else
|
||||
strcpy(fName, "");
|
||||
strcpy(fName, "???");
|
||||
|
||||
if(interface)
|
||||
interface->AddProtocol(this);
|
||||
interface.AddProtocol(this);
|
||||
}
|
||||
|
||||
|
||||
PPPProtocol::~PPPProtocol()
|
||||
{
|
||||
if(Interface())
|
||||
Interface()->RemoveProtocol(this);
|
||||
Interface().RemoveProtocol(this);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPProtocol::InitCheck() const
|
||||
{
|
||||
if(!Interface() || !Settings())
|
||||
if(!Settings())
|
||||
return B_ERROR;
|
||||
|
||||
return B_OK;
|
||||
@ -50,13 +50,10 @@ PPPProtocol::SetEnabled(bool enabled = true)
|
||||
{
|
||||
fEnabled = enabled;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
if(!enabled) {
|
||||
if(IsUp() || IsGoingUp())
|
||||
Down();
|
||||
} else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface()->IsUp())
|
||||
} else if(!IsUp() && !IsGoingUp() && IsUpRequested() && Interface().IsUp())
|
||||
Up();
|
||||
}
|
||||
|
||||
@ -65,16 +62,32 @@ status_t
|
||||
PPPProtocol::Control(uint32 op, void *data, size_t length)
|
||||
{
|
||||
switch(op) {
|
||||
// TODO:
|
||||
// get:
|
||||
// - name
|
||||
// - protocol, address family
|
||||
// - status (Is(Going)Up/Down/UpRequested/Enabled)
|
||||
// set:
|
||||
// - enabled
|
||||
case PPPC_GET_HANDLER_INFO: {
|
||||
if(length < sizeof(ppp_handler_info_t) || !data)
|
||||
return B_ERROR;
|
||||
|
||||
ppp_handler_info *info = (ppp_handler_info*) data;
|
||||
memset(info, 0, sizeof(ppp_handler_info_t));
|
||||
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:
|
||||
return B_ERROR;
|
||||
return PPP_UNHANDLED;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -107,10 +120,7 @@ PPPProtocol::UpFailedEvent()
|
||||
{
|
||||
fConnectionStatus = PPP_DOWN_PHASE;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
Interface()->StateMachine().UpFailedEvent(this);
|
||||
Interface().StateMachine().UpFailedEvent(this);
|
||||
}
|
||||
|
||||
|
||||
@ -119,10 +129,7 @@ PPPProtocol::UpEvent()
|
||||
{
|
||||
fConnectionStatus = PPP_ESTABLISHED_PHASE;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
Interface()->StateMachine().UpEvent(this);
|
||||
Interface().StateMachine().UpEvent(this);
|
||||
}
|
||||
|
||||
|
||||
@ -131,8 +138,5 @@ PPPProtocol::DownEvent()
|
||||
{
|
||||
fConnectionStatus = PPP_DOWN_PHASE;
|
||||
|
||||
if(!Interface())
|
||||
return;
|
||||
|
||||
Interface()->StateMachine().DownEvent(this);
|
||||
Interface().StateMachine().DownEvent(this);
|
||||
}
|
||||
|
@ -185,12 +185,12 @@ PPPStateMachine::UpEvent(PPPInterface *interface)
|
||||
|
||||
if(Phase() == PPP_ESTABLISHMENT_PHASE) {
|
||||
// this is the first interface that went up
|
||||
Interface()->SetLinkMTU(interface->LinkMTU());
|
||||
Interface()->SetMRU(interface->MRU());
|
||||
locker.UnlockNow();
|
||||
ThisLayerUp();
|
||||
} else if(Interface()->LinkMTU() > interface->LinkMTU())
|
||||
Interface()->SetLinkMTU(interface->LinkMTU());
|
||||
// linkMTU should always be the smallest value of all children
|
||||
} else if(Interface()->MRU() > interface->MRU())
|
||||
Interface()->SetMRU(interface->MRU());
|
||||
// MRU should always be the smallest value of all children
|
||||
|
||||
NewState(PPP_OPENED_STATE);
|
||||
}
|
||||
@ -201,8 +201,8 @@ PPPStateMachine::DownEvent(PPPInterface *interface)
|
||||
{
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
uint32 linkMTU = 0;
|
||||
// the new linkMTU
|
||||
uint32 MRU = 0;
|
||||
// the new MRU
|
||||
|
||||
Interface()->CalculateBaudRate();
|
||||
|
||||
@ -214,17 +214,17 @@ PPPStateMachine::DownEvent(PPPInterface *interface)
|
||||
child = Interface()->ChildAt(index);
|
||||
|
||||
if(child && child->IsUp()) {
|
||||
// set linkMTU to the smallest value of all children
|
||||
if(linkMTU == 0)
|
||||
linkMTU = child->LinkMTU();
|
||||
else if(linkMTU > child->LinkMTU())
|
||||
linkMTU = child->LinkMTU();
|
||||
// set MRU to the smallest value of all children
|
||||
if(MRU == 0)
|
||||
MRU = child->MRU();
|
||||
else if(MRU > child->MRU())
|
||||
MRU = child->MRU();
|
||||
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
Interface()->SetLinkMTU(linkMTU);
|
||||
Interface()->SetMRU(MRU);
|
||||
|
||||
if(count == 0) {
|
||||
locker.UnlockNow();
|
||||
@ -1463,10 +1463,10 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 type
|
||||
int32 adjust = 0;
|
||||
// adjust packet size by this value if packet is too big
|
||||
if(packet->m_flags & M_PKTHDR) {
|
||||
if((uint32) packet->m_pkthdr.len > Interface()->LinkMTU())
|
||||
adjust = Interface()->LinkMTU() - packet->m_pkthdr.len;
|
||||
} else if(packet->m_len > Interface()->LinkMTU())
|
||||
adjust = Interface()->LinkMTU() - packet->m_len;
|
||||
if((uint32) packet->m_pkthdr.len > Interface()->MRU())
|
||||
adjust = Interface()->MRU() - packet->m_pkthdr.len;
|
||||
} else if(packet->m_len > Interface()->MRU())
|
||||
adjust = Interface()->MRU() - packet->m_len;
|
||||
|
||||
if(adjust != 0)
|
||||
m_adj(packet, adjust);
|
||||
|
Loading…
Reference in New Issue
Block a user