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:
Waldemar Kornewald
2003-08-30 12:40:25 +00:00
parent d72bf645f0
commit 990e20ecdf
10 changed files with 291 additions and 53 deletions
@@ -9,14 +9,15 @@
#define _K_PPP_CONFIGURE_PACKET__H #define _K_PPP_CONFIGURE_PACKET__H
#include <mbuf.h> #include <mbuf.h>
#include <List.h>
typedef struct configure_item { typedef struct ppp_configure_item {
uint8 type; uint8 type;
uint8 length; uint8 length;
int8 data[0]; int8 data[0];
// the data follows this structure // the data follows this structure
} configure_item; } ppp_configure_item;
class PPPConfigurePacket { class PPPConfigurePacket {
@@ -27,7 +28,7 @@ class PPPConfigurePacket {
public: public:
PPPConfigurePacket(uint8 code); PPPConfigurePacket(uint8 code);
PPPConfigurePacket(mbuf *data); PPPConfigurePacket(mbuf *packet);
~PPPConfigurePacket(); ~PPPConfigurePacket();
bool SetCode(uint8 code); bool SetCode(uint8 code);
@@ -39,16 +40,18 @@ class PPPConfigurePacket {
uint8 ID() const uint8 ID() const
{ return fID; } { return fID; }
void AddItem(const configure_item *item); bool AddItem(const ppp_configure_item *item, int32 index = -1);
bool RemoveItem(const configure_item *item); bool RemoveItem(ppp_configure_item *item);
int32 CountItems() const; int32 CountItems() const
configure_item *ItemAt(int32 index) 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 // the user is responsible for freeing the mbuf
private: private:
uint8 fCode, fID; uint8 fCode, fID;
List<ppp_configure_item*> fItems;
}; };
+1 -1
View File
@@ -14,7 +14,7 @@
typedef uint32 interface_id; typedef uint32 interface_id;
// various constants // various constants
#define PPP_PULSE_RATE 750000 #define PPP_PULSE_RATE 500000
// settings keys // settings keys
#define PPP_DISONNECT_AFTER_IDLE_SINCE_KEY "DisonnectAfterIdleSince" #define PPP_DISONNECT_AFTER_IDLE_SINCE_KEY "DisonnectAfterIdleSince"
+2 -1
View File
@@ -53,7 +53,8 @@ class PPPDevice {
// how many bytes are waiting to be sent? // how many bytes are waiting to be sent?
virtual status_t Send(mbuf *packet) = 0; 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); status_t PassToInterface(mbuf *packet);
// This will pass the packet to the interface's queue. // This will pass the packet to the interface's queue.
// Do not call Interface::ReceiveFromDevice directly // Do not call Interface::ReceiveFromDevice directly
@@ -196,6 +196,8 @@ class PPPInterface {
List<ppp_module_info*> fModules; List<ppp_module_info*> fModules;
BLocker& fLock; BLocker& fLock;
status_t fInitStatus;
}; };
+8
View File
@@ -50,6 +50,14 @@ class PPPLCP : public PPPProtocol {
uint32 AdditionalOverhead() const; uint32 AdditionalOverhead() const;
// the overhead caused by the target, the device, and the interface // 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: private:
List<PPPOptionHandler*> fOptionHandlers; List<PPPOptionHandler*> fOptionHandlers;
@@ -60,7 +60,7 @@ class PPPProtocol {
{ return fConnectionStatus == PPP_TERMINATION_PHASE; } { return fConnectionStatus == PPP_TERMINATION_PHASE; }
virtual status_t Send(mbuf *packet) = 0; 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(); virtual void Pulse();
@@ -6,3 +6,133 @@
//--------------------------------------------------------------------- //---------------------------------------------------------------------
#include "KPPPConfigurePacket.h" #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;
}
+29 -25
View File
@@ -23,11 +23,8 @@
// TODO: // TODO:
// - report module errors (when loading in ctor) // - implement timers with support for settings next time instead of receiving timer
// (in InitCheck(), too) // events
// - 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
// needed for redial: // needed for redial:
@@ -82,7 +79,7 @@ PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
if(!value) if(!value)
fDisconnectAfterIdleSince = 0; fDisconnectAfterIdleSince = 0;
else else
fDisconnectAfterIdleSince = atoi(value); fDisconnectAfterIdleSince = atoi(value) * 1000000;
if(fDisconnectAfterIdleSince < 0) if(fDisconnectAfterIdleSince < 0)
fDisconnectAfterIdleSince = 0; fDisconnectAfterIdleSince = 0;
@@ -111,14 +108,18 @@ PPPInterface::PPPInterface(uint32 ID, driver_settings *settings,
// auto redial is disabled by default // auto redial is disabled by default
// load all protocols and the device // 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() PPPInterface::~PPPInterface()
{ {
fLock.Lock(); if(fLock.Lock() != B_OK)
// make sure no thread wants to call Unlock() on fLock after it is deleted return;;
// make sure no thread wants to call Unlock() on fLock after it is deleted
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
@@ -127,19 +128,24 @@ PPPInterface::~PPPInterface()
stop_ifq(InQueue()); stop_ifq(InQueue());
wait_for_thread(fInQueueThread, &tmp); wait_for_thread(fInQueueThread, &tmp);
// TODO: Down();
// kill (or wait for) fRedialThread UnregisterInterface();
// 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
// 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); put_module((module_info**) &fManager);
} }
@@ -155,7 +161,7 @@ PPPInterface::Delete()
status_t status_t
PPPInterface::InitCheck() const PPPInterface::InitCheck() const
{ {
if(!fSettings || !fManager) if(!fSettings || !fManager || fInitStatus != B_OK)
return B_ERROR; return B_ERROR;
// sub-interfaces should have a device // sub-interfaces should have a device
@@ -188,7 +194,7 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
// add: // add:
// - routing Control() to encapsulators/protocols/option_handlers // - routing Control() to encapsulators/protocols/option_handlers
// (calling their Control() method) // (calling their Control() method)
// - adding modules in right mode // - adding modules
// - setting AutoRedial and DialOnDemand // - setting AutoRedial and DialOnDemand
@@ -992,8 +998,6 @@ PPPInterface::Pulse()
return; return;
} }
StateMachine().TimerEvent();
if(Device()) if(Device())
Device()->Pulse(); Device()->Pulse();
+96 -3
View File
@@ -8,20 +8,26 @@
#include "KPPPLCP.h" #include "KPPPLCP.h"
#define PPP_PROTOCOL_OVERHEAD 2
// TODO: // TODO:
// - add LCP extension handlers // - add LCP extension handlers
PPPLCP::PPPLCP(PPPInterface& interface) PPPLCP::PPPLCP(PPPInterface& interface)
: PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL : PPPProtocol("LCP", PPP_ESTABLISHMENT_PHASE, PPP_LCP_PROTOCOL,
, AF_UNSPEC, &interface, NULL, PPP_ALWAYS_ALLOWED), AF_UNSPEC, &interface, NULL, PPP_ALWAYS_ALLOWED),
fTarget(NULL) fTarget(NULL)
{ {
SetUpRequested(false);
// the state machine does everything for us
} }
PPPLCP::~PPPLCP() PPPLCP::~PPPLCP()
{ {
while(CountOptionHandlers())
delete OptionHandlerAt(0);
} }
@@ -66,7 +72,7 @@ PPPLCP::OptionHandlerAt(int32 index) const
} }
uint32 uint32
PPPLCP::AdditionalOverhead const PPPLCP::AdditionalOverhead() const
{ {
uint32 overhead += PPP_PROTOCOL_OVERHEAD; uint32 overhead += PPP_PROTOCOL_OVERHEAD;
@@ -77,3 +83,90 @@ PPPLCP::AdditionalOverhead const
return overhead; 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();
}
+11 -14
View File
@@ -10,12 +10,6 @@
#define PPP_STATE_MACHINE_TIMEOUT 3000000 #define PPP_STATE_MACHINE_TIMEOUT 3000000
// TODO:
// do not forget to reset authentication status when:
// - connection is lost
// - reconfiguring?
// - terminating
// - ...
PPPStateMachine::PPPStateMachine(PPPInterface& interface) PPPStateMachine::PPPStateMachine(PPPInterface& interface)
: fInterface(&interface), fPhase(PPP_DOWN_PHASE), : fInterface(&interface), fPhase(PPP_DOWN_PHASE),
@@ -23,7 +17,6 @@ PPPStateMachine::PPPStateMachine(PPPInterface& interface)
fAuthenticationStatus(PPP_NOT_AUTHENTICATED), fAuthenticationStatus(PPP_NOT_AUTHENTICATED),
fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED), fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED),
fAuthenticationName(NULL), fPeerAuthenticationName(NULL), fAuthenticationName(NULL), fPeerAuthenticationName(NULL),
fAuthenticatorIndex(-1), fPeerAuthenticatorIndex(-1),
fMaxTerminate(2), fMaxConfigure(10), fMaxNak(5), fMaxTerminate(2), fMaxConfigure(10), fMaxNak(5),
fRequestID(0), fTerminateID(0), fNextTimeout(0) fRequestID(0), fTerminateID(0), fNextTimeout(0)
{ {
@@ -49,6 +42,7 @@ PPPStateMachine::NextID()
void void
PPPStateMachine::NewState(PPP_STATE next) PPPStateMachine::NewState(PPP_STATE next)
{ {
// maybe we do not need the timer anymore
if(next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE) if(next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE)
fNextTimeout = 0; fNextTimeout = 0;
@@ -1385,11 +1379,13 @@ void
PPPStateMachine::SendTerminateRequest() PPPStateMachine::SendTerminateRequest()
{ {
mbuf *m = m_gethdr(MT_DATA); mbuf *m = m_gethdr(MT_DATA);
if(!request) if(!m)
return; return;
--fTerminateCounter; --fTerminateCounter;
m->m_len = 4;
// reserve some space for other protocols // reserve some space for other protocols
m->m_data += LCP().AdditionalOverhead(); m->m_data += LCP().AdditionalOverhead();
@@ -1423,8 +1419,6 @@ PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol, uint8 type)
else else
length = 4; length = 4;
M_PREPEND(packet, length + LCP().AdditionalOverhead());
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) {
@@ -1437,11 +1431,14 @@ PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol, uint8 type)
m_adj(packet, adjust); m_adj(packet, adjust);
lcp_packet *reject = mtod(packet, lcp_packet*); lcp_packet *reject = mtod(packet, lcp_packet*);
data->code = type; reject->code = type;
data->id = NextID(); reject->id = NextID();
data->length = (uint16) htons(reject->m_pkthdr.len); 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) if(type == PPP_PROTOCOL_REJECT)
memcpy(&data->data, &protocol, sizeof(protocol)); memcpy(&data->data, &protocol, sizeof(protocol));