Implemented nearly everything.
TODO: - implement Control() methods - write an authentication option handler - write an MRU option handler I will need to write the jamfile... git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4415 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d72bf645f0
commit
990e20ecdf
@ -9,14 +9,15 @@
|
||||
#define _K_PPP_CONFIGURE_PACKET__H
|
||||
|
||||
#include <mbuf.h>
|
||||
#include <List.h>
|
||||
|
||||
|
||||
typedef struct configure_item {
|
||||
typedef struct ppp_configure_item {
|
||||
uint8 type;
|
||||
uint8 length;
|
||||
int8 data[0];
|
||||
// the data follows this structure
|
||||
} configure_item;
|
||||
} ppp_configure_item;
|
||||
|
||||
|
||||
class PPPConfigurePacket {
|
||||
@ -27,7 +28,7 @@ class PPPConfigurePacket {
|
||||
|
||||
public:
|
||||
PPPConfigurePacket(uint8 code);
|
||||
PPPConfigurePacket(mbuf *data);
|
||||
PPPConfigurePacket(mbuf *packet);
|
||||
~PPPConfigurePacket();
|
||||
|
||||
bool SetCode(uint8 code);
|
||||
@ -39,16 +40,18 @@ class PPPConfigurePacket {
|
||||
uint8 ID() const
|
||||
{ return fID; }
|
||||
|
||||
void AddItem(const configure_item *item);
|
||||
bool RemoveItem(const configure_item *item);
|
||||
int32 CountItems() const;
|
||||
configure_item *ItemAt(int32 index) const;
|
||||
bool AddItem(const ppp_configure_item *item, int32 index = -1);
|
||||
bool RemoveItem(ppp_configure_item *item);
|
||||
int32 CountItems() const
|
||||
{ return fItems.CountItems(); }
|
||||
ppp_configure_item *ItemAt(int32 index) const;
|
||||
|
||||
mbuf *ToMbuf(uint32 reserve = 0, uint32 maxSize = 0);
|
||||
mbuf *ToMbuf(uint32 reserve = 0);
|
||||
// the user is responsible for freeing the mbuf
|
||||
|
||||
private:
|
||||
uint8 fCode, fID;
|
||||
List<ppp_configure_item*> fItems;
|
||||
};
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
typedef uint32 interface_id;
|
||||
|
||||
// various constants
|
||||
#define PPP_PULSE_RATE 750000
|
||||
#define PPP_PULSE_RATE 500000
|
||||
|
||||
// settings keys
|
||||
#define PPP_DISONNECT_AFTER_IDLE_SINCE_KEY "DisonnectAfterIdleSince"
|
||||
|
@ -53,7 +53,8 @@ class PPPDevice {
|
||||
// how many bytes are waiting to be sent?
|
||||
|
||||
virtual status_t Send(mbuf *packet) = 0;
|
||||
// this should enqueue the packet and return immediately
|
||||
// This should enqueue the packet and return immediately.
|
||||
// The device is responsible for freeing the packet.
|
||||
status_t PassToInterface(mbuf *packet);
|
||||
// This will pass the packet to the interface's queue.
|
||||
// Do not call Interface::ReceiveFromDevice directly
|
||||
|
@ -196,6 +196,8 @@ class PPPInterface {
|
||||
List<ppp_module_info*> fModules;
|
||||
|
||||
BLocker& fLock;
|
||||
|
||||
status_t fInitStatus;
|
||||
};
|
||||
|
||||
|
||||
|
@ -50,6 +50,14 @@ class PPPLCP : public PPPProtocol {
|
||||
|
||||
uint32 AdditionalOverhead() const;
|
||||
// the overhead caused by the target, the device, and the interface
|
||||
|
||||
virtual bool Up();
|
||||
virtual bool Down();
|
||||
|
||||
virtual status_t Send(mbuf *packet);
|
||||
virtual status_t Receive(mbuf *packet, uint16 protocol);
|
||||
|
||||
virtual void Pulse();
|
||||
|
||||
private:
|
||||
List<PPPOptionHandler*> fOptionHandlers;
|
||||
|
@ -60,7 +60,7 @@ class PPPProtocol {
|
||||
{ return fConnectionStatus == PPP_TERMINATION_PHASE; }
|
||||
|
||||
virtual status_t Send(mbuf *packet) = 0;
|
||||
virtual status_t Receive(mbuf *packet) = 0;
|
||||
virtual status_t Receive(mbuf *packet, uint16 protocol) = 0;
|
||||
|
||||
virtual void Pulse();
|
||||
|
||||
|
@ -6,3 +6,133 @@
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include "KPPPConfigurePacket.h"
|
||||
|
||||
|
||||
PPPConfigurePacket::PPPConfigurePacket(uint8 code)
|
||||
: fCode(code)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PPPConfigurePacket::PPPConfigurePacket(mbuf *packet)
|
||||
{
|
||||
// decode packet
|
||||
lcp_packet *data = mtod(packet, lcp_packet*);
|
||||
|
||||
if(!SetCode(data->code))
|
||||
return;
|
||||
|
||||
if(data->length < 4)
|
||||
return;
|
||||
// there are no items (or one corrupted item)
|
||||
|
||||
int32 position = 0;
|
||||
ppp_configure_item *item;
|
||||
|
||||
while(position <= data->length - 4) {
|
||||
item = data->data + position;
|
||||
position += item->length;
|
||||
|
||||
AddItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PPPConfigurePacket::~PPPConfigurePacket()
|
||||
{
|
||||
for(int32 index = 0; index < CountItems(); index++)
|
||||
free(ItemAt(index));
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PPPConfigurePacket::SetCode(uint8 code)
|
||||
{
|
||||
// only configure codes are allowed!
|
||||
if(code < PPP_CONFIGURE_REQUEST || code > PPP_CONFIGURE_REJECT)
|
||||
return false;
|
||||
|
||||
fCode = code;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PPPConfigurePacket::AddItem(const ppp_configure_item *item, int32 index = -1)
|
||||
{
|
||||
if(item->length < 2)
|
||||
return false;
|
||||
|
||||
ppp_configure_item *add = malloc(item->length);
|
||||
memcpy(add, item, item->length);
|
||||
|
||||
bool status;
|
||||
if(index < 0)
|
||||
status = fItems.AddItem(add);
|
||||
else
|
||||
status = fItems.AddItem(add, index);
|
||||
if(!status) {
|
||||
free(add);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PPPConfigurePacket::RemoveItem(ppp_configure_item *item)
|
||||
{
|
||||
if(!fItems.HasItem(item))
|
||||
return false;
|
||||
|
||||
fItems.RemoveItem(item);
|
||||
free(item);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ppp_configure_item*
|
||||
PPPConfigurePacket::ItemAt(int32 index) const
|
||||
{
|
||||
ppp_configure_item *item = fItems.ItemAt(index);
|
||||
|
||||
if(item == fItems.GetDefaultItem())
|
||||
return NULL;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
mbuf*
|
||||
PPPConfigurePacket::ToMbuf(uint32 reserve = 0)
|
||||
{
|
||||
mbuf *packet = m_gethdr(MT_DATA);
|
||||
packet->m_data += reserve;
|
||||
|
||||
lcp_packet *data = mtod(packet, lcp_packet*);
|
||||
|
||||
data->code = Code();
|
||||
|
||||
uint8 length = 0;
|
||||
ppp_configure_item *item;
|
||||
|
||||
for(int32 index = 0; index < CountItems(); index++) {
|
||||
item = ItemAt(index);
|
||||
|
||||
if(0xFF - length < item->length) {
|
||||
m_freem(packet);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(data->data + length, item, item->length);
|
||||
length += item->length;
|
||||
}
|
||||
|
||||
data->length = length + 2;
|
||||
packet->m_len = data->length;
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
@ -23,11 +23,8 @@
|
||||
|
||||
|
||||
// TODO:
|
||||
// - report module errors (when loading in ctor)
|
||||
// (in InitCheck(), too)
|
||||
// - add free-list for driver_settings that were loaded by Control()
|
||||
// - implement timers
|
||||
// - maybe some protocols must go down instead of being reset -> add flag for this
|
||||
// - implement timers with support for settings next time instead of receiving timer
|
||||
// events
|
||||
|
||||
|
||||
// needed for redial:
|
||||
@ -82,7 +79,7 @@ PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
|
||||
if(!value)
|
||||
fDisconnectAfterIdleSince = 0;
|
||||
else
|
||||
fDisconnectAfterIdleSince = atoi(value);
|
||||
fDisconnectAfterIdleSince = atoi(value) * 1000000;
|
||||
|
||||
if(fDisconnectAfterIdleSince < 0)
|
||||
fDisconnectAfterIdleSince = 0;
|
||||
@ -111,14 +108,18 @@ PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
|
||||
// auto redial is disabled by default
|
||||
|
||||
// load all protocols and the device
|
||||
LoadModules(fSettings, 0, fSettings->parameter_count);
|
||||
if(LoadModules(fSettings, 0, fSettings->parameter_count))
|
||||
fInitStatus = B_OK;
|
||||
else
|
||||
fInitStatus = B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
PPPInterface::~PPPInterface()
|
||||
{
|
||||
fLock.Lock();
|
||||
// make sure no thread wants to call Unlock() on fLock after it is deleted
|
||||
if(fLock.Lock() != B_OK)
|
||||
return;;
|
||||
// make sure no thread wants to call Unlock() on fLock after it is deleted
|
||||
|
||||
Report(PPP_DESTRUCTION_REPORT, 0, NULL, 0);
|
||||
// tell all listeners that we are being destroyed
|
||||
@ -127,19 +128,24 @@ PPPInterface::~PPPInterface()
|
||||
stop_ifq(InQueue());
|
||||
wait_for_thread(fInQueueThread, &tmp);
|
||||
|
||||
// TODO:
|
||||
// kill (or wait for) fRedialThread
|
||||
// remove our iface, so that nobody will access it:
|
||||
// go down if up
|
||||
// unregister from ppp_manager
|
||||
// delete children/remove from parent
|
||||
// destroy and remove:
|
||||
// device
|
||||
// protocols
|
||||
// encapsulators
|
||||
// option handlers
|
||||
Down();
|
||||
UnregisterInterface();
|
||||
|
||||
// put all modules (in fModules)
|
||||
wait_for_thread(fRedialThread, &tmp);
|
||||
|
||||
while(CountChildren())
|
||||
ChildAt(0)->Delete();
|
||||
|
||||
delete Device();
|
||||
|
||||
while(CountProtocols())
|
||||
delete ProtocolAt(0);
|
||||
|
||||
while(FirstEncapsulator())
|
||||
delete FirstEncapsulator();
|
||||
|
||||
for(int32 index = 0; index < fModules.CountItems(); index++)
|
||||
put_module((module_info**) &fModules.ItemAt(index));
|
||||
|
||||
put_module((module_info**) &fManager);
|
||||
}
|
||||
@ -155,7 +161,7 @@ PPPInterface::Delete()
|
||||
status_t
|
||||
PPPInterface::InitCheck() const
|
||||
{
|
||||
if(!fSettings || !fManager)
|
||||
if(!fSettings || !fManager || fInitStatus != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
// sub-interfaces should have a device
|
||||
@ -188,7 +194,7 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
|
||||
// add:
|
||||
// - routing Control() to encapsulators/protocols/option_handlers
|
||||
// (calling their Control() method)
|
||||
// - adding modules in right mode
|
||||
// - adding modules
|
||||
// - setting AutoRedial and DialOnDemand
|
||||
|
||||
|
||||
@ -992,8 +998,6 @@ PPPInterface::Pulse()
|
||||
return;
|
||||
}
|
||||
|
||||
StateMachine().TimerEvent();
|
||||
|
||||
if(Device())
|
||||
Device()->Pulse();
|
||||
|
||||
|
@ -8,20 +8,26 @@
|
||||
#include "KPPPLCP.h"
|
||||
|
||||
|
||||
#define PPP_PROTOCOL_OVERHEAD 2
|
||||
|
||||
// TODO:
|
||||
// - add LCP extension handlers
|
||||
|
||||
|
||||
PPPLCP::PPPLCP(PPPInterface& interface)
|
||||
: PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL
|
||||
, AF_UNSPEC, &interface, NULL, PPP_ALWAYS_ALLOWED),
|
||||
: PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL,
|
||||
AF_UNSPEC, &interface, NULL, PPP_ALWAYS_ALLOWED),
|
||||
fTarget(NULL)
|
||||
{
|
||||
SetUpRequested(false);
|
||||
// the state machine does everything for us
|
||||
}
|
||||
|
||||
|
||||
PPPLCP::~PPPLCP()
|
||||
{
|
||||
while(CountOptionHandlers())
|
||||
delete OptionHandlerAt(0);
|
||||
}
|
||||
|
||||
|
||||
@ -66,7 +72,7 @@ PPPLCP::OptionHandlerAt(int32 index) const
|
||||
}
|
||||
|
||||
uint32
|
||||
PPPLCP::AdditionalOverhead const
|
||||
PPPLCP::AdditionalOverhead() const
|
||||
{
|
||||
uint32 overhead += PPP_PROTOCOL_OVERHEAD;
|
||||
|
||||
@ -77,3 +83,90 @@ PPPLCP::AdditionalOverhead const
|
||||
|
||||
return overhead;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PPPLCP::Up()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PPPLCP::Down()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPLCP::Send(mbuf *packet)
|
||||
{
|
||||
if(!Interface())
|
||||
return B_ERROR;
|
||||
|
||||
return Interface()->Send(packet, PPP_LCP_PROTOCOL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPLCP::Receive(mbuf *packet, uint16 protocol)
|
||||
{
|
||||
if(protocol != PPP_LCP_PROTOCOL)
|
||||
return PPP_UNHANDLED;
|
||||
|
||||
lcp_packet *data = mtod(packet, lcp_packet*);
|
||||
|
||||
if(ntohs(data->length) < 4)
|
||||
return B_ERROR;
|
||||
|
||||
switch(data->code) {
|
||||
case PPP_CONFIGURE_REQUEST:
|
||||
StateMachine().RCREvent(packet);
|
||||
break;
|
||||
|
||||
case PPP_CONFIGURE_ACK:
|
||||
StateMachine().RCAEvent(packet);
|
||||
break;
|
||||
|
||||
case PPP_CONFIGURE_NAK:
|
||||
case PPP_CONFIGURE_REJECT:
|
||||
StateMachine().RCNEvent(packet);
|
||||
break;
|
||||
|
||||
case PPP_TERMINATE_REQUEST:
|
||||
StateMachine().RTREvent(packet);
|
||||
break;
|
||||
|
||||
case PPP_TERMINATE_ACK:
|
||||
StateMachine().RTAEvent(packet);
|
||||
break;
|
||||
|
||||
case PPP_CODE_REJECT:
|
||||
StateMachine().RXJEvent(packet);
|
||||
break;
|
||||
|
||||
case PPP_PROTOCOL_REJECT:
|
||||
StateMachine().RXJEvent(packet);
|
||||
break;
|
||||
|
||||
case PPP_ECHO_REQUEST:
|
||||
StateMachine().RXREvent(packet);
|
||||
break;
|
||||
|
||||
case PPP_ECHO_REPLY:
|
||||
case PPP_DISCARD_REQUEST:
|
||||
// do nothing
|
||||
break;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PPPLCP::Pulse()
|
||||
{
|
||||
StateMachine().TimerEvent();
|
||||
}
|
||||
|
@ -10,12 +10,6 @@
|
||||
|
||||
#define PPP_STATE_MACHINE_TIMEOUT 3000000
|
||||
|
||||
// TODO:
|
||||
// do not forget to reset authentication status when:
|
||||
// - connection is lost
|
||||
// - reconfiguring?
|
||||
// - terminating
|
||||
// - ...
|
||||
|
||||
PPPStateMachine::PPPStateMachine(PPPInterface& interface)
|
||||
: fInterface(&interface), fPhase(PPP_DOWN_PHASE),
|
||||
@ -23,7 +17,6 @@ PPPStateMachine::PPPStateMachine(PPPInterface& interface)
|
||||
fAuthenticationStatus(PPP_NOT_AUTHENTICATED),
|
||||
fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED),
|
||||
fAuthenticationName(NULL), fPeerAuthenticationName(NULL),
|
||||
fAuthenticatorIndex(-1), fPeerAuthenticatorIndex(-1),
|
||||
fMaxTerminate(2), fMaxConfigure(10), fMaxNak(5),
|
||||
fRequestID(0), fTerminateID(0), fNextTimeout(0)
|
||||
{
|
||||
@ -49,6 +42,7 @@ PPPStateMachine::NextID()
|
||||
void
|
||||
PPPStateMachine::NewState(PPP_STATE next)
|
||||
{
|
||||
// maybe we do not need the timer anymore
|
||||
if(next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE)
|
||||
fNextTimeout = 0;
|
||||
|
||||
@ -1385,11 +1379,13 @@ void
|
||||
PPPStateMachine::SendTerminateRequest()
|
||||
{
|
||||
mbuf *m = m_gethdr(MT_DATA);
|
||||
if(!request)
|
||||
if(!m)
|
||||
return;
|
||||
|
||||
--fTerminateCounter;
|
||||
|
||||
m->m_len = 4;
|
||||
|
||||
// reserve some space for other protocols
|
||||
m->m_data += LCP().AdditionalOverhead();
|
||||
|
||||
@ -1423,8 +1419,6 @@ PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol, uint8 type)
|
||||
else
|
||||
length = 4;
|
||||
|
||||
M_PREPEND(packet, length + LCP().AdditionalOverhead());
|
||||
|
||||
int32 adjust = 0;
|
||||
// adjust packet size by this value if packet is too big
|
||||
if(packet->m_flags & M_PKTHDR) {
|
||||
@ -1437,11 +1431,14 @@ PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol, uint8 type)
|
||||
m_adj(packet, adjust);
|
||||
|
||||
lcp_packet *reject = mtod(packet, lcp_packet*);
|
||||
data->code = type;
|
||||
data->id = NextID();
|
||||
data->length = (uint16) htons(reject->m_pkthdr.len);
|
||||
reject->code = type;
|
||||
reject->id = NextID();
|
||||
if(packet->m_flags & M_PKTHDR)
|
||||
reject->length = htons(packet->m_pkthdr.len);
|
||||
else
|
||||
reject->length = htons(packet->m_len);
|
||||
|
||||
protocol = (uint16) htons(protocol);
|
||||
protocol = htons(protocol);
|
||||
if(type == PPP_PROTOCOL_REJECT)
|
||||
memcpy(&data->data, &protocol, sizeof(protocol));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user