From 990e20ecdf08556b2df5501c24d086016e69b870 Mon Sep 17 00:00:00 2001 From: Waldemar Kornewald Date: Sat, 30 Aug 2003 12:40:25 +0000 Subject: [PATCH] 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 --- .../net/ppp/headers/KPPPConfigurePacket.h | 19 +-- src/tests/kits/net/ppp/headers/KPPPDefs.h | 2 +- src/tests/kits/net/ppp/headers/KPPPDevice.h | 3 +- .../kits/net/ppp/headers/KPPPInterface.h | 2 + src/tests/kits/net/ppp/headers/KPPPLCP.h | 8 ++ src/tests/kits/net/ppp/headers/KPPPProtocol.h | 2 +- .../kits/net/ppp/src/KPPPConfigurePacket.cpp | 130 ++++++++++++++++++ src/tests/kits/net/ppp/src/KPPPInterface.cpp | 54 ++++---- src/tests/kits/net/ppp/src/KPPPLCP.cpp | 99 ++++++++++++- .../kits/net/ppp/src/KPPPStateMachine.cpp | 25 ++-- 10 files changed, 291 insertions(+), 53 deletions(-) diff --git a/src/tests/kits/net/ppp/headers/KPPPConfigurePacket.h b/src/tests/kits/net/ppp/headers/KPPPConfigurePacket.h index 338f290e57..1e9c8a3600 100644 --- a/src/tests/kits/net/ppp/headers/KPPPConfigurePacket.h +++ b/src/tests/kits/net/ppp/headers/KPPPConfigurePacket.h @@ -9,14 +9,15 @@ #define _K_PPP_CONFIGURE_PACKET__H #include +#include -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 fItems; }; diff --git a/src/tests/kits/net/ppp/headers/KPPPDefs.h b/src/tests/kits/net/ppp/headers/KPPPDefs.h index 22c3d20513..8530301d1e 100644 --- a/src/tests/kits/net/ppp/headers/KPPPDefs.h +++ b/src/tests/kits/net/ppp/headers/KPPPDefs.h @@ -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" diff --git a/src/tests/kits/net/ppp/headers/KPPPDevice.h b/src/tests/kits/net/ppp/headers/KPPPDevice.h index fa261ef191..682c5e525d 100644 --- a/src/tests/kits/net/ppp/headers/KPPPDevice.h +++ b/src/tests/kits/net/ppp/headers/KPPPDevice.h @@ -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 diff --git a/src/tests/kits/net/ppp/headers/KPPPInterface.h b/src/tests/kits/net/ppp/headers/KPPPInterface.h index 9b883f555a..c000507a07 100644 --- a/src/tests/kits/net/ppp/headers/KPPPInterface.h +++ b/src/tests/kits/net/ppp/headers/KPPPInterface.h @@ -196,6 +196,8 @@ class PPPInterface { List fModules; BLocker& fLock; + + status_t fInitStatus; }; diff --git a/src/tests/kits/net/ppp/headers/KPPPLCP.h b/src/tests/kits/net/ppp/headers/KPPPLCP.h index 524ffb38ee..3425d93f15 100644 --- a/src/tests/kits/net/ppp/headers/KPPPLCP.h +++ b/src/tests/kits/net/ppp/headers/KPPPLCP.h @@ -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 fOptionHandlers; diff --git a/src/tests/kits/net/ppp/headers/KPPPProtocol.h b/src/tests/kits/net/ppp/headers/KPPPProtocol.h index 6095ee3c0f..4e31a147eb 100644 --- a/src/tests/kits/net/ppp/headers/KPPPProtocol.h +++ b/src/tests/kits/net/ppp/headers/KPPPProtocol.h @@ -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(); diff --git a/src/tests/kits/net/ppp/src/KPPPConfigurePacket.cpp b/src/tests/kits/net/ppp/src/KPPPConfigurePacket.cpp index 7f5e79e69f..90b59aa43b 100644 --- a/src/tests/kits/net/ppp/src/KPPPConfigurePacket.cpp +++ b/src/tests/kits/net/ppp/src/KPPPConfigurePacket.cpp @@ -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; +} diff --git a/src/tests/kits/net/ppp/src/KPPPInterface.cpp b/src/tests/kits/net/ppp/src/KPPPInterface.cpp index 1f841aa79c..650214e9a9 100644 --- a/src/tests/kits/net/ppp/src/KPPPInterface.cpp +++ b/src/tests/kits/net/ppp/src/KPPPInterface.cpp @@ -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(); diff --git a/src/tests/kits/net/ppp/src/KPPPLCP.cpp b/src/tests/kits/net/ppp/src/KPPPLCP.cpp index d22955deca..fbea4c90d8 100644 --- a/src/tests/kits/net/ppp/src/KPPPLCP.cpp +++ b/src/tests/kits/net/ppp/src/KPPPLCP.cpp @@ -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(); +} diff --git a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp index e53dc5582f..0c4aa80a8c 100644 --- a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp +++ b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp @@ -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));