Added some helper functions and improved PPPLCPExtension handling.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4519 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald 2003-09-06 23:54:35 +00:00
parent c7c8500780
commit 283ad63871
6 changed files with 190 additions and 49 deletions

View File

@ -11,7 +11,10 @@
#include "net_module.h"
#define PPP_MANAGER_MODULE_NAME "network/interfaces/ppp"
#define PPP_MANAGER_MODULE_NAME "network/interfaces/ppp"
#define PPP_UNDEFINED_INTERFACE_ID 0
// create_interface() returns this value on failure
// this allows you to ask for specific interface_ids
enum PPP_INTERFACE_FILTER {
@ -29,6 +32,7 @@ typedef struct ppp_manager_info {
void (*delete_interface)(interface_id ID);
// this marks the interface for deletion
void (*remove_interface)(interface_id ID);
// remove the interface from database (make sure you can delete it yourself!)
ifnet* (*register_interface)(interface_id ID);
bool (*unregister_interface)(interface_id ID);

View File

@ -45,7 +45,17 @@ class PPPStateMachine {
{ return fPhase; }
uint8 NextID();
// return the next id for lcp_packets
// return the next id for LCP packets
void SetMagicNumber(uint32 magicNumber)
{ fMagicNumber = magicNumber; }
uint32 MagicNumber() const
{ return fMagicNumber; }
// public actions
bool Reconfigure();
bool SendEchoRequest();
bool SendDiscardRequest();
// public events
void AuthenticationRequested();
@ -124,7 +134,7 @@ class PPPStateMachine {
void ThisLayerFinished();
void InitializeRestartCount();
void ZeroRestartCount();
void SendConfigureRequest();
bool SendConfigureRequest();
void SendConfigureAck(struct mbuf *packet);
void SendConfigureNak(struct mbuf *packet);
void SendTerminateRequest();
@ -147,6 +157,7 @@ class PPPStateMachine {
PPP_STATE fState;
vint32 fID;
uint32 fMagicNumber;
PPP_AUTHENTICATION_STATUS fAuthenticationStatus,
fPeerAuthenticationStatus;
@ -157,8 +168,8 @@ class PPPStateMachine {
// counters and timers
int32 fMaxRequest, fMaxTerminate, fMaxNak;
int32 fRequestCounter, fTerminateCounter, fNakCounter;
uint8 fRequestID, fTerminateID;
// the ID we used for the last configure/terminate request
uint8 fRequestID, fTerminateID, fEchoID;
// the ID we used for the last configure/terminate/echo request
bigtime_t fNextTimeout;
};

View File

@ -86,6 +86,7 @@ typedef struct ppp_control_info {
typedef struct ppp_interface_info {
const driver_settings *settings;
struct ifnet *ifnet;
PPP_MODE mode;
PPP_STATE state;

View File

@ -240,6 +240,7 @@ PPPInterface::Control(uint32 op, void *data, size_t length)
ppp_interface_info *info = (ppp_interface_info*) data;
memset(info, 0, sizeof(ppp_interface_info_t));
info->settings = Settings();
info->ifnet = Ifnet();
info->mode = Mode();
info->state = State();
info->phase = Phase();

View File

@ -159,14 +159,26 @@ PPPLCP::Send(struct mbuf *packet)
status_t
PPPLCP::Receive(struct mbuf *packet, uint16 protocol)
{
if(!packet)
return B_ERROR;
if(protocol != PPP_LCP_PROTOCOL)
return PPP_UNHANDLED;
struct mbuf *copy = m_gethdr(MT_DATA);
if(copy) {
copy->m_data += AdditionalOverhead();
copy->m_len = packet->m_len;
memcpy(copy->m_data, packet->m_data, copy->m_len);
}
ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*);
if(ntohs(data->length) < 4)
return B_ERROR;
bool handled = true;
switch(data->code) {
case PPP_CONFIGURE_REQUEST:
StateMachine().RCREvent(packet);
@ -198,36 +210,62 @@ PPPLCP::Receive(struct mbuf *packet, uint16 protocol)
break;
case PPP_ECHO_REQUEST:
case PPP_ECHO_REPLY:
case PPP_DISCARD_REQUEST:
StateMachine().RXREvent(packet);
break;
case PPP_ECHO_REPLY:
case PPP_DISCARD_REQUEST:
default:
m_freem(packet);
// do nothing
break;
default: {
status_t result = PPP_UNHANDLED;
// try to find LCP extensions that can handle this code
PPPLCPExtension *extension;
for(int32 index = 0; index < CountLCPExtensions(); index++) {
extension = LCPExtensionAt(index);
if(extension->IsEnabled() && extension->Code() == data->code)
result = extension->Receive(packet, data->code);
handled = false;
}
if(!copy)
return handled ? B_OK : B_ERROR;
packet = copy;
copy = NULL;
status_t result = B_OK;
// Try to find LCP extensions that can handle this code.
// We must duplicate the packet in order to ask all handlers.
PPPLCPExtension *extension;
for(int32 index = 0; index < CountLCPExtensions(); index++) {
extension = LCPExtensionAt(index);
if(extension->IsEnabled() && extension->Code() == data->code) {
if(!copy) {
copy = m_gethdr(MT_DATA);
if(!copy)
return B_ERROR;
copy->m_data += AdditionalOverhead();
copy->m_len = packet->m_len;
memcpy(copy->m_data, packet->m_data, copy->m_len);
}
if(result == PPP_UNHANDLED) {
StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT);
return PPP_REJECTED;
}
result = extension->Receive(copy, data->code);
return result;
if(result == B_OK) {
copy = NULL;
handled = true;
} else if(result != PPP_UNHANDLED)
return result;
}
}
return B_OK;
if(copy)
m_freem(copy);
if(!handled) {
StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT);
return PPP_REJECTED;
}
if(packet)
m_freem(packet);
return result;
}

View File

@ -23,12 +23,12 @@
PPPStateMachine::PPPStateMachine(PPPInterface& interface)
: fInterface(&interface), fLCP(interface.LCP()), fPhase(PPP_DOWN_PHASE),
fState(PPP_INITIAL_STATE), fID(system_time() & 0xFF),
fState(PPP_INITIAL_STATE), fID(system_time() & 0xFF), fMagicNumber(0),
fAuthenticationStatus(PPP_NOT_AUTHENTICATED),
fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED),
fAuthenticationName(NULL), fPeerAuthenticationName(NULL),
fMaxRequest(10), fMaxTerminate(2), fMaxNak(5),
fRequestID(0), fTerminateID(0), fNextTimeout(0)
fRequestID(0), fTerminateID(0), fEchoID(0), fNextTimeout(0)
{
}
@ -89,6 +89,77 @@ PPPStateMachine::NewPhase(PPP_PHASE next)
}
// public actions
bool
PPPStateMachine::Reconfigure()
{
LockerHelper locker(fLock);
if(State() < PPP_REQ_SENT_STATE)
return false;
NewState(PPP_REQ_SENT_STATE);
NewPhase(PPP_ESTABLISHMENT_PHASE);
DownProtocols();
DownEncapsulators();
ResetOptionHandlers();
locker.UnlockNow();
return SendConfigureRequest();
}
bool
PPPStateMachine::SendEchoRequest()
{
if(State() != PPP_OPENED_STATE)
return false;
struct mbuf *packet = m_gethdr(MT_DATA);
if(!packet)
return false;
packet->m_data += LCP().AdditionalOverhead();
packet->m_len = 8;
// echo requests are at least eight bytes long
ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
request->code = PPP_ECHO_REQUEST;
request->id = NextID();
fEchoID = request->id;
request->length = htons(packet->m_len);
memcpy(request->data, &fMagicNumber, sizeof(fMagicNumber));
return LCP.Send(packet) == B_OK;
}
bool
PPPStateMachine::SendDiscardRequest()
{
if(State() != PPP_OPENED_STATE)
return false;
struct mbuf *packet = m_gethdr(MT_DATA);
if(!packet)
return false;
packet->m_data += LCP().AdditionalOverhead();
packet->m_len = 8;
// discard requests are at least eight bytes long
ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
request->code = PPP_DISCARD_REQUEST;
request->id = NextID();
request->length = htons(packet->m_len);
memcpy(request->data, &fMagicNumber, sizeof(fMagicNumber));
return LCP.Send(packet) == B_OK;
}
// authentication events
void
PPPStateMachine::AuthenticationRequested()
@ -1067,6 +1138,8 @@ PPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocol,
void
PPPStateMachine::RXJGoodEvent(struct mbuf *packet)
{
// This method does not m_freem(packet) because the acceptable rejects are
// also passed to the parent. RXJEvent() will m_freem(packet) when needed.
LockerHelper locker(fLock);
switch(State()) {
@ -1135,6 +1208,11 @@ PPPStateMachine::RXREvent(struct mbuf *packet)
{
ppp_lcp_packet *echo = mtod(packet, ppp_lcp_packet*);
if(echo->code == PPP_ECHO_REPLY && echo->id != fEchoID) {
// TODO:
// log that we got a reply, but no request was sent
}
switch(State()) {
case PPP_INITIAL_STATE:
case PPP_STARTING_STATE:
@ -1145,6 +1223,7 @@ PPPStateMachine::RXREvent(struct mbuf *packet)
if(echo->code == PPP_ECHO_REQUEST)
SendEchoReply(packet);
return;
// this prevents the packet from being freed
default:
;
@ -1401,7 +1480,7 @@ PPPStateMachine::ZeroRestartCount()
}
void
bool
PPPStateMachine::SendConfigureRequest()
{
--fRequestCounter;
@ -1414,19 +1493,19 @@ PPPStateMachine::SendConfigureRequest()
// add all items
if(!LCP().OptionHandlerAt(index)->AddToRequest(&request)) {
CloseEvent();
return;
return false;
}
}
LCP().Send(request.ToMbuf(LCP().AdditionalOverhead()));
return LCP().Send(request.ToMbuf(LCP().AdditionalOverhead())) == B_OK;
}
void
bool
PPPStateMachine::SendConfigureAck(struct mbuf *packet)
{
if(!packet)
return;
return false;
mtod(packet, ppp_lcp_packet*)->code = PPP_CONFIGURE_ACK;
PPPConfigurePacket ack(packet);
@ -1435,15 +1514,15 @@ PPPStateMachine::SendConfigureAck(struct mbuf *packet)
for(int32 index = 0; index < LCP().CountOptionHandlers(); index++)
LCP().OptionHandlerAt(index)->SendingAck(&ack);
LCP().Send(packet);
return LCP().Send(packet) == B_OK;
}
void
bool
PPPStateMachine::SendConfigureNak(struct mbuf *packet)
{
if(!packet)
return;
return false;
ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*);
if(nak->code == PPP_CONFIGURE_NAK) {
@ -1454,16 +1533,16 @@ PPPStateMachine::SendConfigureNak(struct mbuf *packet)
--fNakCounter;
}
LCP().Send(packet);
return LCP().Send(packet) == B_OK;
}
void
bool
PPPStateMachine::SendTerminateRequest()
{
struct mbuf *m = m_gethdr(MT_DATA);
if(!m)
return;
return false;
--fTerminateCounter;
@ -1477,11 +1556,11 @@ PPPStateMachine::SendTerminateRequest()
request->id = fTerminateID = NextID();
request->length = htons(4);
LCP().Send(m);
return LCP().Send(m) == B_OK;
}
void
bool
PPPStateMachine::SendTerminateAck(struct mbuf *request = NULL)
{
struct mbuf *reply = request;
@ -1491,7 +1570,7 @@ PPPStateMachine::SendTerminateAck(struct mbuf *request = NULL)
if(!reply) {
reply = m_gethdr(MT_DATA);
if(!reply)
return;
return false;
reply->m_data += LCP().AdditionalOverhead();
reply->m_len = 4;
@ -1502,17 +1581,17 @@ PPPStateMachine::SendTerminateAck(struct mbuf *request = NULL)
ack = mtod(reply, ppp_lcp_packet*);
ack->code = PPP_TERMINATE_ACK;
ack->length = 4;
ack->length = htons(4);
LCP().Send(reply);
return LCP().Send(reply) == B_OK;
}
void
bool
PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 code)
{
if(!packet)
return;
return false;
int32 length;
// additional space needed for this reject
@ -1547,21 +1626,28 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocol, uint8 code
if(code == PPP_PROTOCOL_REJECT)
memcpy(&reject->data, &protocol, sizeof(protocol));
LCP().Send(packet);
return LCP().Send(packet) == B_OK;
}
void
bool
PPPStateMachine::SendEchoReply(struct mbuf *request)
{
if(!request)
return;
return false;
ppp_lcp_packet *reply = mtod(request, ppp_lcp_packet*);
reply->code = PPP_ECHO_REPLY;
// the request becomes a reply
LCP().Send(request);
if(request->m_flags & M_PKTHDR)
request->m_pkthdr.len = 8;
request->m_len = 8;
memcpy(reply->data, &fMagicNumber, sizeof(fMagicNumber));
return LCP().Send(request) == B_OK;
}