Worked on events and actions.

StateMachine now waits until all protocols/encapsulators have finished going up before entering next phase.
Added StateMachine methods to support main interfaces (multilink).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4055 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald
2003-07-24 12:00:53 +00:00
parent 4c7e909c5f
commit ec3447e61f
6 changed files with 233 additions and 69 deletions
@@ -66,6 +66,9 @@ class PPPEncapsulator {
// call the interface's SendToDevice function // call the interface's SendToDevice function
protected: protected:
void UpStarted();
void DownStarted();
void UpFailedEvent(); void UpFailedEvent();
void UpEvent(); void UpEvent();
void DownEvent(); void DownEvent();
@@ -135,6 +135,8 @@ class PPPInterface {
PPPLCP fLCP; PPPLCP fLCP;
ifnet *fIfnet; ifnet *fIfnet;
ppp_manager_info *fManager;
uint32 fLinkMTU, fMRU, fHeaderLength; uint32 fLinkMTU, fMRU, fHeaderLength;
PPPInterface *fParent; PPPInterface *fParent;
@@ -51,6 +51,9 @@ class PPPProtocol {
virtual status_t Receive(mbuf *packet) = 0; virtual status_t Receive(mbuf *packet) = 0;
protected: protected:
void UpStarted();
void DownStarted();
void UpFailedEvent(); void UpFailedEvent();
void UpEvent(); void UpEvent();
void DownEvent(); void DownEvent();
@@ -80,6 +80,7 @@ class PPPStateMachine {
// private StateMachine methods // private StateMachine methods
void NewState(PPP_STATE next); void NewState(PPP_STATE next);
void NewPhase(PPP_PHASE next);
// private events // private events
void OpenEvent(); void OpenEvent();
@@ -92,7 +93,7 @@ class PPPStateMachine {
void RCNEvent(mbuf *packet); void RCNEvent(mbuf *packet);
void RTREvent(mbuf *packet); void RTREvent(mbuf *packet);
void RTAEvent(mbuf *packet); void RTAEvent(mbuf *packet);
void RUCEvent(mbuf *packet, uint16 protocol); void RUCEvent(mbuf *packet, uint16 protocol, uint8 type);
void RXJGoodEvent(mbuf *packet); void RXJGoodEvent(mbuf *packet);
void RXJBadEvent(mbuf *packet); void RXJBadEvent(mbuf *packet);
void RXREvent(mbuf *packet); void RXREvent(mbuf *packet);
@@ -115,8 +116,11 @@ class PPPStateMachine {
void SendConfigureNak(mbuf *packet); void SendConfigureNak(mbuf *packet);
void SendTerminateRequest(); void SendTerminateRequest();
void SendTerminateAck(mbuf *request); void SendTerminateAck(mbuf *request);
void SendCodeReject(mbuf *packet, uint16 protocol); void SendCodeReject(mbuf *packet, uint16 protocol, uint8 type);
void SendEchoReply(mbuf *request); void SendEchoReply(mbuf *request);
void BringHandlersUp();
uint32 BringPhaseUp();
private: private:
PPPInterface *fInterface; PPPInterface *fInterface;
+29 -31
View File
@@ -29,6 +29,9 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL
fAccessing(0), fChildrenCount(0), fDevice(NULL), fFirstEncapsulator(NULL), fAccessing(0), fChildrenCount(0), fDevice(NULL), fFirstEncapsulator(NULL),
fGeneralLock(StateMachine().Locker()) fGeneralLock(StateMachine().Locker())
{ {
if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &fManager) != B_OK)
fManager = NULL;
// are we a multilink subinterface? // are we a multilink subinterface?
if(parent && parent->IsMultilink()) { if(parent && parent->IsMultilink()) {
fParent = parent; fParent = parent;
@@ -72,6 +75,8 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL
PPPInterface::~PPPInterface() PPPInterface::~PPPInterface()
{ {
put_module((module_info**) &fManager);
// TODO: // TODO:
// remove our iface, so that nobody will access it: // remove our iface, so that nobody will access it:
// go down if up // go down if up
@@ -89,7 +94,7 @@ PPPInterface::~PPPInterface()
status_t status_t
PPPInterface::InitCheck() const PPPInterface::InitCheck() const
{ {
if(!fSettings) if(!fSettings || !fManager)
return B_ERROR; return B_ERROR;
// sub-interfaces should have a device // sub-interfaces should have a device
@@ -118,14 +123,10 @@ PPPInterface::RegisterInterface()
if(IsMultilink() && Parent() && Parent()->RegisterInterface()) if(IsMultilink() && Parent() && Parent()->RegisterInterface())
return true; return true;
ppp_manager_info *manager; if(!fManager)
if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &manager) != B_OK)
return false; return false;
fIfnet = manager->add_interface(this); fIfnet = fManager->add_interface(this);
put_module((module_info**) &manager);
if(!fIfnet) if(!fIfnet)
return false; return false;
@@ -145,15 +146,12 @@ PPPInterface::UnregisterInterface()
if(IsMultilink() && Parent()) if(IsMultilink() && Parent())
return true; return true;
ppp_manager_info *manager; if(!fManager)
if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &manager) != B_OK)
return false; return false;
manager->remove_interface(this); fManager->remove_interface(this);
fIfnet = NULL; fIfnet = NULL;
put_module((module_info**) &manager);
return true; return true;
} }
@@ -406,6 +404,10 @@ PPPInterface::RemoveChild(PPPInterface *child)
child->SetParent(NULL); child->SetParent(NULL);
// parents cannot exist without their children
if(CountChildren() == 0 && fManager)
fManager->delete_interface(this);
CalculateMRU(); CalculateMRU();
return true; return true;
@@ -623,13 +625,13 @@ PPPInterface::Send(mbuf *packet, uint16 protocol)
// we must pass the basic tests! // we must pass the basic tests!
if(InitCheck() != B_OK) { if(InitCheck() != B_OK) {
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
// test whether are going down // test whether are going down
if(Phase() == PPP_TERMINATION_PHASE) { if(Phase() == PPP_TERMINATION_PHASE) {
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
@@ -646,7 +648,7 @@ PPPInterface::Send(mbuf *packet, uint16 protocol)
// never send normal protocols when we are down // never send normal protocols when we are down
if(!IsUp()) { if(!IsUp()) {
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
@@ -722,7 +724,7 @@ PPPInterface::Receive(mbuf *packet, uint16 protocol)
return Parent->Receive(packet, protocol); return Parent->Receive(packet, protocol);
if(result == PPP_UNHANDLED) if(result == PPP_UNHANDLED)
m_free(packet); m_freem(packet);
return PPP_DISCARDED; return PPP_DISCARDED;
else { else {
StateMachine()->RUCEvent(packet, protocol); StateMachine()->RUCEvent(packet, protocol);
@@ -743,13 +745,13 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
// do we have a device (as main interface)? // do we have a device (as main interface)?
// did we load all modules? // did we load all modules?
if(InitCheck() != B_OK) { if(InitCheck() != B_OK) {
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
// test whether are going down // test whether are going down
if(Phase() == PPP_TERMINATION_PHASE) { if(Phase() == PPP_TERMINATION_PHASE) {
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
@@ -769,12 +771,12 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
) )
) )
) { ) {
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
// encode in ppp frame // encode in ppp frame
M_PREPEND(packet, sizeof(uint16)); packet = M_PREPEND(packet, sizeof(uint16));
if(packet == NULL) if(packet == NULL)
return B_ERROR; return B_ERROR;
@@ -789,14 +791,14 @@ PPPInterface::SendToDevice(mbuf *packet, uint16 protocol)
// check if packet is too big for device // check if packet is too big for device
if((packet->m_flags & M_PKTHDR && packet->m_pkt_hdr.len > LinkMTU()) if((packet->m_flags & M_PKTHDR && packet->m_pkt_hdr.len > LinkMTU())
|| packet->m_len > LinkMTU()) { || packet->m_len > LinkMTU()) {
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
return Device()->Send(packet); return Device()->Send(packet);
} else { } else {
// the multilink encapsulator should have sent it to some child interface // the multilink encapsulator should have sent it to some child interface
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
} }
@@ -811,7 +813,7 @@ PPPInterface::ReceiveFromDevice(mbuf *packet)
return B_ERROR; return B_ERROR;
if(!InitCheck()) { if(!InitCheck()) {
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
@@ -827,7 +829,7 @@ PPPInterface::ReceiveFromDevice(mbuf *packet)
// the packet // the packet
if(!packet->m_pkthdr.rcvif) { if(!packet->m_pkthdr.rcvif) {
m_free(packet); m_freem(packet);
return B_ERROR; return B_ERROR;
} }
} }
@@ -852,15 +854,11 @@ PPPInterface::CalculateMRU()
fMRU -= fHeaderLength; fMRU -= fHeaderLength;
if(Parent())
Parent()->CalculateMRU();
for(int32 i = 0; i < fChildren.CountItems(); i++)
fMRU += fChildren.ItemAt(i)->MRU();
// add our subinterfaces' MRU (so we have the MRRU)
if(Ifnet()) { if(Ifnet()) {
Ifnet()->if_mtu = fMRU; Ifnet()->if_mtu = fMRU;
Ifnet()->if_hdrlen = fHeaderLength; Ifnet()->if_hdrlen = fHeaderLength;
} }
if(Parent())
Parent()->CalculateMRU();
} }
+190 -36
View File
@@ -1,11 +1,15 @@
#include "KPPPStateMachine.h" #include "KPPPStateMachine.h"
// TODO:
// do not forget to reset authentication status when needed
PPPStateMachine::PPPStateMachine(PPPInterface& interface) PPPStateMachine::PPPStateMachine(PPPInterface& interface)
: fInterface(&interface), fPhase(PPP_DOWN_PHASE), : fInterface(&interface), fPhase(PPP_DOWN_PHASE),
fState(PPP_INITIAL_STATE), fID(system_time() & 0xFF), fState(PPP_INITIAL_STATE), fID(system_time() & 0xFF),
fAuthenticationStatus(PPP_NOT_AUTHENTICATED), fAuthenticationStatus(PPP_NOT_AUTHENTICATED),
fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED), fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED),
fAuthenticationName(NULL), fPeerAuthenticationName(NULL),
fAuthenticatorIndex(-1), fPeerAuthenticatorIndex(-1), fAuthenticatorIndex(-1), fPeerAuthenticatorIndex(-1),
fMaxTerminate(2), fMaxConfigure(10), fMaxNak(5), fMaxTerminate(2), fMaxConfigure(10), fMaxNak(5),
fRequestID(0), fTerminateID(0), fTimeout(0) fRequestID(0), fTerminateID(0), fTimeout(0)
@@ -15,6 +19,8 @@ PPPStateMachine::PPPStateMachine(PPPInterface& interface)
PPPStateMachine::~PPPStateMachine() PPPStateMachine::~PPPStateMachine()
{ {
free(fAuthenticationName);
free(fPeerAuthenticationName);
} }
@@ -30,6 +36,7 @@ PPPStateMachine::NextID()
void void
PPPStateMachine::NewState(PPP_STATE next) PPPStateMachine::NewState(PPP_STATE next)
{ {
// TODO:
// if(State() == PPP_OPENED_STATE) // if(State() == PPP_OPENED_STATE)
// ResetOptionHandlers(); // ResetOptionHandlers();
@@ -37,90 +44,163 @@ PPPStateMachine::NewState(PPP_STATE next)
} }
void
PPPStateMachine::NewPhase(PPP_PHASE next)
{
// Report a down event to parent if we are not usable anymore.
// The report threads get their notification later.
if(Phase() == PPP_ESTABLISHED_PHASE && Interface()->Parent())
Interface()->Parent()->StateMachine().DownEvent(Interface());
// there is nothing after established phase and nothing before down phase
if(next > PPP_ESTABLISHED_PHASE)
fPhase = PPP_ESTABLISHED_PHASE;
else if(next < PPP_DOWN_PHASE)
fPhase = PPP_DOWN_PHASE;
else
fPhase = next;
}
// authentication events // authentication events
void void
PPPStateMachine::AuthenticationRequested() PPPStateMachine::AuthenticationRequested()
{ {
// IMPLEMENT ME! LockerHelper locker(fLock);
fAuthenticationStatus = PPP_AUTHENTICATING;
free(fAuthenticationName);
} }
void void
PPPStateMachine::AuthenticationAccepted(const char *name) PPPStateMachine::AuthenticationAccepted(const char *name)
{ {
// IMPLEMENT ME! LockerHelper locker(fLock);
fAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL;
free(fAuthenticationName);
fAuthenticationName = strdup(name);
} }
void void
PPPStateMachine::AuthenticationDenied(const char *name) PPPStateMachine::AuthenticationDenied(const char *name)
{ {
// IMPLEMENT ME! LockerHelper locker(fLock);
fAuthenticationStatus = PPP_AUTHENTICATION_FAILED;
free(fAuthenticationName);
fAuthenticationName = strdup(name);
} }
const char* const char*
PPPStateMachine::AuthenticationName() const PPPStateMachine::AuthenticationName() const
{ {
// IMPLEMENT ME! LockerHelper locker(fLock);
return fAuthenticationName;
} }
void void
PPPStateMachine::PeerAuthenticationRequested() PPPStateMachine::PeerAuthenticationRequested()
{ {
// IMPLEMENT ME! LockerHelper locker(fLock);
fPeerAuthenticationStatus = PPP_AUTHENTICATING;
free(fPeerAuthenticationName);
} }
void void
PPPStateMachine::PeerAuthenticationAccepted(const char *name) PPPStateMachine::PeerAuthenticationAccepted(const char *name)
{ {
// IMPLEMENT ME! LockerHelper locker(fLock);
fPeerAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL;
free(fPeerAuthenticationName);
fPeerAuthenticationName = strdup(name);
} }
void void
PPPStateMachine::PeerAuthenticationDenied(const char *name) PPPStateMachine::PeerAuthenticationDenied(const char *name)
{ {
// IMPLEMENT ME! LockerHelper locker(fLock);
fPeerAuthenticationStatus = PPP_AUTHENTICATION_FAILED;
free(fPeerAuthenticationName);
fPeerAuthenticationName = strdup(name);
} }
const char* const char*
PPPStateMachine::PeerAuthenticationName() const PPPStateMachine::PeerAuthenticationName() const
{ {
// IMPLEMENT ME! LockerHelper locker(fLock);
return fPeerAuthenticationName;
} }
void void
PPPStateMachine::UpFailedEvent(PPPInterface *interface) PPPStateMachine::UpFailedEvent(PPPInterface *interface)
{ {
// TODO:
// log that an interface did not go up
} }
void void
PPPStateMachine::UpEvent(PPPInterface *interface) PPPStateMachine::UpEvent(PPPInterface *interface)
{ {
if(Phase() < PPP_ESTABLISHMENT_PHASE) {
Interface()->UnregisterInterface();
return;
}
if(Interface()->IsMultilink() && !Interface()->Parent())
Interface()->RegisterInterface();
} }
void void
PPPStateMachine::DownEvent(PPPInterface *interface) PPPStateMachine::DownEvent(PPPInterface *interface)
{ {
// when all children are down we should not be registered
if(Interface()->IsMultilink() && !Interface()->Parent()) {
uint32 count = 0;
PPPInterface *child;
for(int32 i = 0; i < Interface()->CountChildren(); i++) {
child = Interface()->ChildAt(i);
if(child && child->IsUp())
++count;
}
if(count == 0)
Interface()->UnregisterInterface();
}
} }
void void
PPPStateMachine::UpFailedEvent(PPPProtocol *protocol) PPPStateMachine::UpFailedEvent(PPPProtocol *protocol)
{ {
// All protocols must go up.
CloseEvent();
} }
void void
PPPStateMachine::UpEvent(PPPProtocol *protocol) PPPStateMachine::UpEvent(PPPProtocol *protocol)
{ {
LockerHelper locker(fLock);
if(Phase() >= PPP_ESTABLISHMENT_PHASE)
BringHandlersUp();
} }
@@ -133,12 +213,18 @@ PPPStateMachine::DownEvent(PPPProtocol *protocol)
void void
PPPStateMachine::UpFailedEvent(PPPEncapsulator *encapsulator) PPPStateMachine::UpFailedEvent(PPPEncapsulator *encapsulator)
{ {
// All encapsulators must go up.
CloseEvent();
} }
void void
PPPStateMachine::UpEvent(PPPEncapsulator *encapsulator) PPPStateMachine::UpEvent(PPPEncapsulator *encapsulator)
{ {
LockerHelper locker(fLock);
if(Phase() >= PPP_ESTABLISHMENT_PHASE)
BringHandlersUp();
} }
@@ -160,7 +246,7 @@ PPPStateMachine::TLSNotify()
if(State() == PPP_STARTING_STATE) { if(State() == PPP_STARTING_STATE) {
if(Phase() == PPP_DOWN_PHASE) if(Phase() == PPP_DOWN_PHASE)
fPhase = PPP_ESTABLISHMENT_PHASE; NewPhase(PPP_ESTABLISHMENT_PHASE);
// this says that the device is going up // this says that the device is going up
return true; return true;
} }
@@ -185,7 +271,7 @@ PPPStateMachine::TLFNotify()
} }
// from now on no packets may be sent to the device // from now on no packets may be sent to the device
fPhase = PPP_DOWN_PHASE; NewPhase(PPP_DOWN_PHASE);
return true; return true;
} }
@@ -211,6 +297,8 @@ PPPStateMachine::UpFailedEvent()
// TODO: // TODO:
// report that up failed // report that up failed
// Report(PPP_CONNECTION_REPORT, PPP_UP_FAILED, NULL, 0); // Report(PPP_CONNECTION_REPORT, PPP_UP_FAILED, NULL, 0);
if(Interface()->Parent())
Interface()->Parent()->StateMachine().UpFailedEvent(Interface());
break; break;
default: default:
@@ -285,14 +373,14 @@ PPPStateMachine::DownEvent()
case PPP_CLOSED_STATE: case PPP_CLOSED_STATE:
case PPP_CLOSING_STATE: case PPP_CLOSING_STATE:
NewState(PPP_INITIAL_STATE); NewState(PPP_INITIAL_STATE);
fPhase = PPP_DOWN_PHASE; NewPhase(PPP_DOWN_PHASE);
break; break;
case PPP_STOPPED_STATE: case PPP_STOPPED_STATE:
// The RFC says we should reconnect, but our implementation // The RFC says we should reconnect, but our implementation
// will only do this if auto-redial is enabled (only clients). // will only do this if auto-redial is enabled (only clients).
NewStatus(PPP_STARTING_STATE); NewStatus(PPP_STARTING_STATE);
fPhase = PPP_DOWN_PHASE; NewPhase(PPP_DOWN_PHASE);
// TODO: // TODO:
// report that we lost the connection // report that we lost the connection
@@ -304,7 +392,7 @@ PPPStateMachine::DownEvent()
case PPP_STOPPING_STATE: case PPP_STOPPING_STATE:
NewStatus(PPP_STARTING_STATE); NewStatus(PPP_STARTING_STATE);
fPhase = PPP_DOWN_PHASE; NewPhase(PPP_DOWN_PHASE);
// TODO: // TODO:
// report that we lost the connection // report that we lost the connection
@@ -315,7 +403,7 @@ PPPStateMachine::DownEvent()
case PPP_ACK_RCVD_STATE: case PPP_ACK_RCVD_STATE:
case PPP_ACK_SENT_STATE: case PPP_ACK_SENT_STATE:
NewStatus(PPP_STARTING_STATE); NewStatus(PPP_STARTING_STATE);
fPhase = PPP_DOWN_PHASE; NewPhase(PPP_DOWN_PHASE);
// TODO: // TODO:
// report that we lost the connection // report that we lost the connection
@@ -325,7 +413,7 @@ PPPStateMachine::DownEvent()
case PPP_OPENED_STATE: case PPP_OPENED_STATE:
// tld/1 // tld/1
NewStatus(PPP_STARTING_STATE); NewStatus(PPP_STARTING_STATE);
fPhase = PPP_DOWN_PHASE; NewPhase(PPP_DOWN_PHASE);
// TODO: // TODO:
// report that we lost the connection // report that we lost the connection
@@ -339,8 +427,14 @@ PPPStateMachine::DownEvent()
// maybe we need to redial // maybe we need to redial
if(State() == PPP_STARTING_STATE) { if(State() == PPP_STARTING_STATE) {
if(Interface()->DoesAutoRedial()) { if(Interface()->DoesAutoRedial()) {
NewState(PPP_INITIAL_STATE);
// TODO: // TODO:
// redial using a new thread (maybe interface manager will help us) // redial using a new thread (maybe interface manager will help us)
} else {
if(Interface()->Parent())
Interface()->Parent()->StateMachine().UpFailedEvent(Interface());
// TODO:
// we must delete our interface
} }
} }
} }
@@ -366,7 +460,7 @@ PPPStateMachine::OpenEvent()
} }
NewState(PPP_REQ_SENT_STATE); NewState(PPP_REQ_SENT_STATE);
fPhase = PPP_ESTABLISHMENT_PHASE; NewPhase(PPP_ESTABLISHMENT_PHASE);
InitializeRestartCount(); InitializeRestartCount();
locker.UnlockNow(); locker.UnlockNow();
SendConfigureRequest(); SendConfigureRequest();
@@ -391,7 +485,7 @@ PPPStateMachine::CloseEvent()
case PPP_ACK_RCVD_STATE: case PPP_ACK_RCVD_STATE:
case PPP_ACK_SENT_STATE: case PPP_ACK_SENT_STATE:
NewState(PPP_CLOSING_STATE); NewState(PPP_CLOSING_STATE);
fPhase = PPP_TERMINATION_PHASE; NewPhase(PPP_TERMINATION_PHASE);
InitializeRestartCount(); InitializeRestartCount();
locker.UnlockNow(); locker.UnlockNow();
SendTerminateRequest(); SendTerminateRequest();
@@ -405,7 +499,7 @@ PPPStateMachine::CloseEvent()
// are in PPP_INITIAL_STATE now // are in PPP_INITIAL_STATE now
if(Phase() == PPP_ESTABLISHMENT_PHASE) { if(Phase() == PPP_ESTABLISHMENT_PHASE) {
// the device is already up // the device is already up
fPhase = PPP_DOWN_PHASE; NewPhase(PPP_DOWN_PHASE);
// this says the following DownEvent() was not caused by // this says the following DownEvent() was not caused by
// a connection fault // a connection fault
locker.UnlockNow(); locker.UnlockNow();
@@ -461,7 +555,7 @@ PPPStateMachine::TOBadEvent()
switch(State()) { switch(State()) {
case PPP_CLOSING_STATE: case PPP_CLOSING_STATE:
NewState(PPP_CLOSED_STATE); NewState(PPP_CLOSED_STATE);
fPhase = PPP_TERMINATION_PHASE; NewPhase(PPP_TERMINATION_PHASE);
locker.UnlockNow(); locker.UnlockNow();
ThisLayerFinished(); ThisLayerFinished();
break; break;
@@ -471,7 +565,7 @@ PPPStateMachine::TOBadEvent()
case PPP_ACK_RCVD_STATE: case PPP_ACK_RCVD_STATE:
case PPP_ACK_SENT_STATE: case PPP_ACK_SENT_STATE:
NewState(PPP_STOPPED_STATE); NewState(PPP_STOPPED_STATE);
fPhase = PPP_TERMINATION_PHASE; NewPhase(PPP_TERMINATION_PHASE);
locker.UnlockNow(); locker.UnlockNow();
ThisLayerFinished(); ThisLayerFinished();
break; break;
@@ -574,9 +668,9 @@ PPPStateMachine::RCRBadEvent(mbuf *nak, mbuf *reject)
case PPP_REQ_SENT_STATE: case PPP_REQ_SENT_STATE:
case PPP_ACK_RCVD_STATE: case PPP_ACK_RCVD_STATE:
locker.UnlockNow(); locker.UnlockNow();
if(!nak && mtod(nak, lcp_packet*)->length > 3) if(!nak && ntohs(mtod(nak, lcp_packet*)->length) > 3)
SendConfigureNak(nak); SendConfigureNak(nak);
else if(!reject && mtod(reject, lcp_packet*)->length > 3) else if(!reject && ntohs(mtod(reject, lcp_packet*)->length) > 3)
SendConfigureNak(reject); SendConfigureNak(reject);
break; break;
} }
@@ -790,7 +884,7 @@ PPPStateMachine::RTAEvent(mbuf *packet)
// receive unknown code // receive unknown code
void void
PPPStateMachine::RUCEvent(mbuf *packet, uint16 protocol) PPPStateMachine::RUCEvent(mbuf *packet, uint16 protocol, uint8 type)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
@@ -802,7 +896,7 @@ PPPStateMachine::RUCEvent(mbuf *packet, uint16 protocol)
default: default:
locker.UnlockNow(); locker.UnlockNow();
SendCodeReject(packet, protocol); SendCodeReject(packet, protocol, type);
} }
} }
@@ -972,7 +1066,7 @@ PPPStateMachine::RCREvent(mbuf *packet)
// ReceiveCodeReject // ReceiveCodeReject
// LCP received a code-reject packet and we look if it is acceptable. // LCP received a code/protocol-reject packet and we look if it is acceptable.
// From here we call our Good/Bad counterparts. // From here we call our Good/Bad counterparts.
void void
PPPStateMachine::RXJEvent(mbuf *packet) PPPStateMachine::RXJEvent(mbuf *packet)
@@ -981,6 +1075,7 @@ PPPStateMachine::RXJEvent(mbuf *packet)
if(reject->code == PPP_CODE_REJECT) if(reject->code == PPP_CODE_REJECT)
RXJBadEvent(packet); RXJBadEvent(packet);
// we only have basic codes, so there must be something wrong
else if(reject->code == PPP_PROTOCOL_REJECT) { else if(reject->code == PPP_PROTOCOL_REJECT) {
// disable all handlers for rejected protocol type // disable all handlers for rejected protocol type
uint16 rejected = *((uint16*) reject->data); uint16 rejected = *((uint16*) reject->data);
@@ -994,23 +1089,27 @@ PPPStateMachine::RXJEvent(mbuf *packet)
int32 index; int32 index;
PPPProtocol *protocol_handler; PPPProtocol *protocol_handler;
PPPEncapsulator *encapsulator_handler = fFirstEncapsulator; PPPEncapsulator *encapsulator_handler = Interface()->FirstEncapsulator();
for(index = 0; index < LCP().CountProtocols(); index++) { for(index = 0; index < Interface()->CountProtocols(); index++) {
protocol_handler = LCP().ProtocolAt(index); protocol_handler = Interface()->ProtocolAt(index);
if(protocol_handler && protocol_handler->Protocol() == rejected) if(protocol_handler && protocol_handler->Protocol() == rejected)
protocol_handler->SetEnabled(false); protocol_handler->SetEnabled(false);
// disable protocol // disable protocol
} }
for(; encapsulator_handler; for(; encapsulator_handler;
encapsulator_handler = encapsulator_handler->Next()) { encapsulator_handler = encapsulator_handler->Next()) {
if(encapsulator_handler->Protocol() == rejected) if(encapsulator_handler->Protocol() == rejected)
encapsulator_handler->SetEnabled(false); encapsulator_handler->SetEnabled(false);
// disable encapsulator // disable encapsulator
} }
RXJGoodEvent(packet); RXJGoodEvent(packet);
// notify parent, too
if(Interface()->Parent())
Interface()->Parent()->StateMachine().RXJEvent(packet);
} }
} }
@@ -1027,11 +1126,12 @@ PPPStateMachine::IllegalEvent(PPP_EVENT event)
void void
PPPStateMachine::ThisLayerUp() PPPStateMachine::ThisLayerUp()
{ {
// TODO: LockerHelper locker(fLock);
// bring all P/Es up
// increase until we reach PPP_ESTABLISHED_PHASE or until we actually // We begin with authentication phase and wait until each phase is done.
// find P/Es that need an Up(). // We stop when we reach established phase.
// In this case we continue to increase the phase in UpEvent(P/E). NewPhase(PPP_AUTHENTICATION_PHASE);
BringHandlersUp();
} }
@@ -1163,7 +1263,7 @@ PPPStateMachine::SendTerminateRequest()
lcp_packet *request = mtod(m, lcp_packet*); lcp_packet *request = mtod(m, lcp_packet*);
request->code = PPP_TERMINATE_REQUEST; request->code = PPP_TERMINATE_REQUEST;
request->id = fTerminateID = NextID(); request->id = fTerminateID = NextID();
request->length = 4; request->length = htons(4);
LCP().Send(m); LCP().Send(m);
} }
@@ -1181,7 +1281,7 @@ PPPStateMachine::SendTerminateAck(mbuf *request)
void void
PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol) PPPStateMachine::SendCodeReject(mbuf *packet, uint16 protocol, uint8 type)
{ {
// TODO: // TODO:
// add the packet to the reject and truncate it if needed // add the packet to the reject and truncate it if needed
@@ -1197,3 +1297,57 @@ PPPStateMachine::SendEchoReply(mbuf *request)
LCP().Send(request); LCP().Send(request);
} }
// methods for bringing protocols/encapsulators up
void
PPPStateMachine::BringHandlersUp()
{
while(Phase() <= PPP_ESTABLISHED_PHASE) {
if(BringPhaseUp() > 0)
break;
if(Phase() == PPP_ESTABLISHED_PHASE) {
if(Interface()->Parent())
Interface()->Parent()->StateMachine().UpEvent(Interface());
// TODO:
// Report(PPP_CONNECTION_REPORT, PPP_UP_SUCCESSFUL, NULL, 0);
} else
NewPhase(Phase() + 1);
}
}
// this returns the number of handlers waiting to go up
uint32
PPPStateMachine::BringPhaseUp()
{
uint32 count = 0;
PPPProtocol *protocol_handler;
PPPEncapsulator *encapsulator_handler = Interface()->FirstEncapsulator();
for(int32 index = 0; index < Interface()->CountProtocols(); index++) {
protocol_handler = Interface()->ProtocolAt(index);
if(protocol_handler && protocol_handler->Phase() == Phase()) {
if(protocol_handler->IsUpRequested()) {
++count;
protocol_handler->Up();
} else if(protocol_handler->IsGoingUp())
++count;
}
}
for(; encapsulator_handler;
encapsulator_handler = encapsulator_handler->Next()) {
if(encapsulator_handler && encapsulator_handler->Phase() == Phase()) {
if(encapsulator_handler->IsUpRequested()) {
++count;
encapsulator_handler->Up();
} else if(encapsulator_handler->IsGoingUp())
++count;
}
}
return count;
}