184b580c4SWaldemar Kornewald /*
2fc1cf1a3SAxel Dörfler * Copyright 2003-2007, Waldemar Kornewald <wkornew@gmx.net>
384b580c4SWaldemar Kornewald * Distributed under the terms of the MIT License.
484b580c4SWaldemar Kornewald */
5de2f76e1SWaldemar Kornewald
63f3689bbSWaldemar Kornewald /*! \class KPPPStateMachine
73f3689bbSWaldemar Kornewald \brief PPP state machine belonging to the LCP protocol
83f3689bbSWaldemar Kornewald
93f3689bbSWaldemar Kornewald The state machine is responsible for handling events and state changes.
103f3689bbSWaldemar Kornewald
113f3689bbSWaldemar Kornewald \sa KPPPLCP
123f3689bbSWaldemar Kornewald */
133f3689bbSWaldemar Kornewald
14de2f76e1SWaldemar Kornewald #include <OS.h>
15de2f76e1SWaldemar Kornewald
16de2f76e1SWaldemar Kornewald #include <KPPPInterface.h>
17de2f76e1SWaldemar Kornewald #include <KPPPConfigurePacket.h>
18de2f76e1SWaldemar Kornewald #include <KPPPDevice.h>
19de2f76e1SWaldemar Kornewald #include <KPPPLCPExtension.h>
20de2f76e1SWaldemar Kornewald #include <KPPPOptionHandler.h>
21de2f76e1SWaldemar Kornewald
22abdb7d1aSWaldemar Kornewald #include <KPPPUtils.h>
23f9ad2df8SWaldemar Kornewald
24de2f76e1SWaldemar Kornewald #include <net/if.h>
25*7e66a287SJaroslaw Pelczar #include <arpa/inet.h>
26de2f76e1SWaldemar Kornewald
27e3724c38Smshlyn #include <ByteOrder.h>
28e3724c38Smshlyn #include <net_buffer.h>
29e3724c38Smshlyn #include <NetBufferUtilities.h>
30e3724c38Smshlyn
31e3724c38Smshlyn extern net_buffer_module_info *gBufferModule;
32de2f76e1SWaldemar Kornewald
336ff76cdaSWaldemar Kornewald static const bigtime_t kPPPStateMachineTimeout = 3000000;
344e0ad752SWaldemar Kornewald // 3 seconds
35de2f76e1SWaldemar Kornewald
36de2f76e1SWaldemar Kornewald
373f3689bbSWaldemar Kornewald //! Constructor.
KPPPStateMachine(KPPPInterface & interface)38f9ad2df8SWaldemar Kornewald KPPPStateMachine::KPPPStateMachine(KPPPInterface& interface)
39de2f76e1SWaldemar Kornewald : fInterface(interface),
40de2f76e1SWaldemar Kornewald fLCP(interface.LCP()),
41de2f76e1SWaldemar Kornewald fState(PPP_INITIAL_STATE),
42ca43389aSWaldemar Kornewald fPhase(PPP_DOWN_PHASE),
43de2f76e1SWaldemar Kornewald fID(system_time() & 0xFF),
44de2f76e1SWaldemar Kornewald fMagicNumber(0),
45abdb7d1aSWaldemar Kornewald fLastConnectionReportCode(PPP_REPORT_DOWN_SUCCESSFUL),
46de2f76e1SWaldemar Kornewald fLocalAuthenticationStatus(PPP_NOT_AUTHENTICATED),
47de2f76e1SWaldemar Kornewald fPeerAuthenticationStatus(PPP_NOT_AUTHENTICATED),
48de2f76e1SWaldemar Kornewald fLocalAuthenticationName(NULL),
49de2f76e1SWaldemar Kornewald fPeerAuthenticationName(NULL),
50de2f76e1SWaldemar Kornewald fMaxRequest(10),
51de2f76e1SWaldemar Kornewald fMaxTerminate(2),
52de2f76e1SWaldemar Kornewald fMaxNak(5),
53de2f76e1SWaldemar Kornewald fRequestID(0),
54de2f76e1SWaldemar Kornewald fTerminateID(0),
55de2f76e1SWaldemar Kornewald fEchoID(0),
5684b580c4SWaldemar Kornewald fNextTimeout(0),
57e3724c38Smshlyn fLock(mutex())
58de2f76e1SWaldemar Kornewald {
59e3724c38Smshlyn mutex_init(&fLock, "KPPPStateMachine");
60de2f76e1SWaldemar Kornewald }
61de2f76e1SWaldemar Kornewald
62de2f76e1SWaldemar Kornewald
633f3689bbSWaldemar Kornewald //! Destructor. Frees loaded memory.
~KPPPStateMachine()64f9ad2df8SWaldemar Kornewald KPPPStateMachine::~KPPPStateMachine()
65de2f76e1SWaldemar Kornewald {
66de2f76e1SWaldemar Kornewald free(fLocalAuthenticationName);
67de2f76e1SWaldemar Kornewald free(fPeerAuthenticationName);
68de2f76e1SWaldemar Kornewald }
69de2f76e1SWaldemar Kornewald
70de2f76e1SWaldemar Kornewald
713f3689bbSWaldemar Kornewald //! Creates an ID for the next LCP packet.
72de2f76e1SWaldemar Kornewald uint8
NextID()73f9ad2df8SWaldemar Kornewald KPPPStateMachine::NextID()
74de2f76e1SWaldemar Kornewald {
75de2f76e1SWaldemar Kornewald return (uint8) atomic_add(&fID, 1);
76de2f76e1SWaldemar Kornewald }
77de2f76e1SWaldemar Kornewald
78de2f76e1SWaldemar Kornewald
793f3689bbSWaldemar Kornewald /*! \brief Changes the current state.
803f3689bbSWaldemar Kornewald
813f3689bbSWaldemar Kornewald Remember: NewState() must always be called \e after IllegalEvent() because
823f3689bbSWaldemar Kornewald IllegalEvent() also looks at the current state.
833f3689bbSWaldemar Kornewald */
84de2f76e1SWaldemar Kornewald void
NewState(ppp_state next)85f9ad2df8SWaldemar Kornewald KPPPStateMachine::NewState(ppp_state next)
86de2f76e1SWaldemar Kornewald {
8784b580c4SWaldemar Kornewald TRACE("KPPPSM: NewState(%d) state=%d\n", next, State());
884e0ad752SWaldemar Kornewald
89de2f76e1SWaldemar Kornewald // maybe we do not need the timer anymore
90de2f76e1SWaldemar Kornewald if (next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE)
91de2f76e1SWaldemar Kornewald fNextTimeout = 0;
92de2f76e1SWaldemar Kornewald
93de2f76e1SWaldemar Kornewald if (State() == PPP_OPENED_STATE && next != State())
94de2f76e1SWaldemar Kornewald ResetLCPHandlers();
95de2f76e1SWaldemar Kornewald
96de2f76e1SWaldemar Kornewald fState = next;
97de2f76e1SWaldemar Kornewald }
98de2f76e1SWaldemar Kornewald
99de2f76e1SWaldemar Kornewald
1003f3689bbSWaldemar Kornewald /*! \brief Changes the current phase.
1013f3689bbSWaldemar Kornewald
1023f3689bbSWaldemar Kornewald This method is responsible for setting the \c if_flags and sending the
1033f3689bbSWaldemar Kornewald \c PPP_REPORT_UP_SUCCESSFUL report message.
1043f3689bbSWaldemar Kornewald */
105de2f76e1SWaldemar Kornewald void
NewPhase(ppp_phase next)106f9ad2df8SWaldemar Kornewald KPPPStateMachine::NewPhase(ppp_phase next)
107de2f76e1SWaldemar Kornewald {
1084e0ad752SWaldemar Kornewald #if DEBUG
1094e0ad752SWaldemar Kornewald if (next <= PPP_ESTABLISHMENT_PHASE || next == PPP_ESTABLISHED_PHASE)
11084b580c4SWaldemar Kornewald TRACE("KPPPSM: NewPhase(%d) phase=%d\n", next, Phase());
1114e0ad752SWaldemar Kornewald #endif
1124e0ad752SWaldemar Kornewald
113de2f76e1SWaldemar Kornewald // there is nothing after established phase and nothing before down phase
114de2f76e1SWaldemar Kornewald if (next > PPP_ESTABLISHED_PHASE)
115de2f76e1SWaldemar Kornewald next = PPP_ESTABLISHED_PHASE;
116de2f76e1SWaldemar Kornewald else if (next < PPP_DOWN_PHASE)
117de2f76e1SWaldemar Kornewald next = PPP_DOWN_PHASE;
118de2f76e1SWaldemar Kornewald
119de2f76e1SWaldemar Kornewald // Report a down event to parent if we are not usable anymore.
120de2f76e1SWaldemar Kornewald // The report threads get their notification later.
121de2f76e1SWaldemar Kornewald if (Phase() == PPP_ESTABLISHED_PHASE && next != Phase()) {
122e7452421SWaldemar Kornewald if (Interface().Ifnet()) {
123e3724c38Smshlyn // Interface().Ifnet()->flags &= ~IFF_RUNNING;
124e3724c38Smshlyn Interface().Ifnet()->flags &= ~IFF_UP;
125e7452421SWaldemar Kornewald }
126e7452421SWaldemar Kornewald
127de2f76e1SWaldemar Kornewald if (Interface().Parent())
128de2f76e1SWaldemar Kornewald Interface().Parent()->StateMachine().DownEvent(Interface());
129de2f76e1SWaldemar Kornewald }
130de2f76e1SWaldemar Kornewald
131de2f76e1SWaldemar Kornewald fPhase = next;
132de2f76e1SWaldemar Kornewald
133de2f76e1SWaldemar Kornewald if (Phase() == PPP_ESTABLISHED_PHASE) {
134484a5f0eSWaldemar Kornewald Interface().fConnectedSince = system_time();
135484a5f0eSWaldemar Kornewald
136e7452421SWaldemar Kornewald if (Interface().Ifnet())
137e3724c38Smshlyn Interface().Ifnet()->flags |= IFF_UP;// | IFF_RUNNING;
138de2f76e1SWaldemar Kornewald
139abdb7d1aSWaldemar Kornewald Interface().fConnectAttempt = 0;
140abdb7d1aSWaldemar Kornewald // when we Reconnect() this becomes 1 (the first connection attempt)
141abdb7d1aSWaldemar Kornewald send_data_with_timeout(Interface().fReconnectThread, 0, NULL, 0, 200);
142abdb7d1aSWaldemar Kornewald // abort possible reconnect attempt
143abdb7d1aSWaldemar Kornewald fLastConnectionReportCode = PPP_REPORT_UP_SUCCESSFUL;
14449c2f687SWaldemar Kornewald Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_UP_SUCCESSFUL,
1456cfb4dcaSWaldemar Kornewald &fInterface.fID, sizeof(ppp_interface_id));
146de2f76e1SWaldemar Kornewald }
147de2f76e1SWaldemar Kornewald }
148de2f76e1SWaldemar Kornewald
149de2f76e1SWaldemar Kornewald
150de2f76e1SWaldemar Kornewald // public actions
1513f3689bbSWaldemar Kornewald
1523f3689bbSWaldemar Kornewald //! Reconfigures the state machine. This initiates a new configure request handshake.
153de2f76e1SWaldemar Kornewald bool
Reconfigure()154f9ad2df8SWaldemar Kornewald KPPPStateMachine::Reconfigure()
155de2f76e1SWaldemar Kornewald {
15684b580c4SWaldemar Kornewald TRACE("KPPPSM: Reconfigure() state=%d phase=%d\n", State(), Phase());
1574e0ad752SWaldemar Kornewald
158de2f76e1SWaldemar Kornewald if (State() < PPP_REQ_SENT_STATE)
159de2f76e1SWaldemar Kornewald return false;
160de2f76e1SWaldemar Kornewald
161de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
162de2f76e1SWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
163ca43389aSWaldemar Kornewald // indicates to handlers that we are reconfiguring
164de2f76e1SWaldemar Kornewald
165de2f76e1SWaldemar Kornewald DownProtocols();
166de2f76e1SWaldemar Kornewald ResetLCPHandlers();
167de2f76e1SWaldemar Kornewald
168de2f76e1SWaldemar Kornewald return SendConfigureRequest();
169de2f76e1SWaldemar Kornewald }
170de2f76e1SWaldemar Kornewald
171de2f76e1SWaldemar Kornewald
1723f3689bbSWaldemar Kornewald //! Sends an echo request packet.
173de2f76e1SWaldemar Kornewald bool
SendEchoRequest()174f9ad2df8SWaldemar Kornewald KPPPStateMachine::SendEchoRequest()
175de2f76e1SWaldemar Kornewald {
17684b580c4SWaldemar Kornewald TRACE("KPPPSM: SendEchoRequest() state=%d phase=%d\n", State(), Phase());
1774e0ad752SWaldemar Kornewald
178de2f76e1SWaldemar Kornewald if (State() != PPP_OPENED_STATE)
179de2f76e1SWaldemar Kornewald return false;
180de2f76e1SWaldemar Kornewald
181e3724c38Smshlyn net_buffer *packet = gBufferModule->create(256);
182e3724c38Smshlyn if (packet == NULL)
183de2f76e1SWaldemar Kornewald return false;
184de2f76e1SWaldemar Kornewald
185e3724c38Smshlyn void *data;
186e3724c38Smshlyn status_t status = gBufferModule->append_size(packet, 1492, &data);
187e3724c38Smshlyn if (status == B_OK && data == NULL) {
188e3724c38Smshlyn gBufferModule->free(packet);
189e3724c38Smshlyn return false;
190e3724c38Smshlyn }
191de2f76e1SWaldemar Kornewald
192e3724c38Smshlyn // echo requests are at least eight bytes long
193e3724c38Smshlyn ppp_lcp_packet request;
194e3724c38Smshlyn request.code = PPP_ECHO_REQUEST;
195e3724c38Smshlyn request.id = NextID();
196e3724c38Smshlyn request.length = htons(8);
197e3724c38Smshlyn fEchoID = request.id;
198e3724c38Smshlyn
199e3724c38Smshlyn memcpy(data, &request, sizeof(request));
200e3724c38Smshlyn memcpy(request.data, &fMagicNumber, sizeof(fMagicNumber));
201e3724c38Smshlyn
202e3724c38Smshlyn status = gBufferModule->trim(packet, sizeof(request) + sizeof(fMagicNumber));
203e3724c38Smshlyn if (status < B_OK) {
204e3724c38Smshlyn gBufferModule->free(packet);
205e3724c38Smshlyn return false;
206e3724c38Smshlyn }
207de2f76e1SWaldemar Kornewald
208de2f76e1SWaldemar Kornewald return LCP().Send(packet) == B_OK;
209de2f76e1SWaldemar Kornewald }
210de2f76e1SWaldemar Kornewald
211de2f76e1SWaldemar Kornewald
2123f3689bbSWaldemar Kornewald //! Sends a discard request packet.
213de2f76e1SWaldemar Kornewald bool
SendDiscardRequest()214f9ad2df8SWaldemar Kornewald KPPPStateMachine::SendDiscardRequest()
215de2f76e1SWaldemar Kornewald {
21684b580c4SWaldemar Kornewald TRACE("KPPPSM: SendDiscardRequest() state=%d phase=%d\n", State(), Phase());
2174e0ad752SWaldemar Kornewald
218e3724c38Smshlyn net_buffer *packet = gBufferModule->create(256);
219e3724c38Smshlyn if (packet == NULL)
220de2f76e1SWaldemar Kornewald return false;
221de2f76e1SWaldemar Kornewald
222e3724c38Smshlyn void *data;
223e3724c38Smshlyn status_t status = gBufferModule->append_size(packet, 1492, &data);
224e3724c38Smshlyn if (status == B_OK && data == NULL) {
225e3724c38Smshlyn gBufferModule->free(packet);
226de2f76e1SWaldemar Kornewald return false;
227e3724c38Smshlyn }
228de2f76e1SWaldemar Kornewald
229de2f76e1SWaldemar Kornewald // discard requests are at least eight bytes long
230e3724c38Smshlyn // echo requests are at least eight bytes long
231e3724c38Smshlyn ppp_lcp_packet request;
232e3724c38Smshlyn request.code = PPP_DISCARD_REQUEST;
233e3724c38Smshlyn request.id = NextID();
234e3724c38Smshlyn request.length = htons(8);
235e3724c38Smshlyn fEchoID = request.id;
236de2f76e1SWaldemar Kornewald
237e3724c38Smshlyn memcpy(data, &request, sizeof(request));
238e3724c38Smshlyn memcpy(request.data, &fMagicNumber, sizeof(fMagicNumber));
239e3724c38Smshlyn
240e3724c38Smshlyn status = gBufferModule->trim(packet, sizeof(request) + sizeof(fMagicNumber));
241e3724c38Smshlyn if (status < B_OK) {
242e3724c38Smshlyn gBufferModule->free(packet);
243e3724c38Smshlyn return false;
244e3724c38Smshlyn }
245de2f76e1SWaldemar Kornewald
246de2f76e1SWaldemar Kornewald return LCP().Send(packet) == B_OK;
247de2f76e1SWaldemar Kornewald }
248de2f76e1SWaldemar Kornewald
249de2f76e1SWaldemar Kornewald
250de2f76e1SWaldemar Kornewald // authentication events
2513f3689bbSWaldemar Kornewald
2523f3689bbSWaldemar Kornewald /*! Notification that local authentication is requested.
2533f3689bbSWaldemar Kornewald
2543f3689bbSWaldemar Kornewald NOTE: This must be called \e after \c KPPPProtocol::Up().
2553f3689bbSWaldemar Kornewald */
256de2f76e1SWaldemar Kornewald void
LocalAuthenticationRequested()257f9ad2df8SWaldemar Kornewald KPPPStateMachine::LocalAuthenticationRequested()
258de2f76e1SWaldemar Kornewald {
25984b580c4SWaldemar Kornewald TRACE("KPPPSM: LocalAuthenticationRequested() state=%d phase=%d\n",
2604e0ad752SWaldemar Kornewald State(), Phase());
2614e0ad752SWaldemar Kornewald
262abdb7d1aSWaldemar Kornewald fLastConnectionReportCode = PPP_REPORT_AUTHENTICATION_REQUESTED;
2635a483e4dSWaldemar Kornewald Interface().Report(PPP_CONNECTION_REPORT,
264abdb7d1aSWaldemar Kornewald PPP_REPORT_AUTHENTICATION_REQUESTED, &fInterface.fID,
2655a483e4dSWaldemar Kornewald sizeof(ppp_interface_id));
2665a483e4dSWaldemar Kornewald
267de2f76e1SWaldemar Kornewald fLocalAuthenticationStatus = PPP_AUTHENTICATING;
268de2f76e1SWaldemar Kornewald free(fLocalAuthenticationName);
269de2f76e1SWaldemar Kornewald fLocalAuthenticationName = NULL;
270de2f76e1SWaldemar Kornewald }
271de2f76e1SWaldemar Kornewald
272de2f76e1SWaldemar Kornewald
2733f3689bbSWaldemar Kornewald /*! \brief Notification that local authentication was accepted.
2743f3689bbSWaldemar Kornewald
2753f3689bbSWaldemar Kornewald NOTE: This must be called \e before \c UpEvent().
2763f3689bbSWaldemar Kornewald
2773f3689bbSWaldemar Kornewald \param name The username/login that was accepted.
2783f3689bbSWaldemar Kornewald */
279de2f76e1SWaldemar Kornewald void
LocalAuthenticationAccepted(const char * name)280f9ad2df8SWaldemar Kornewald KPPPStateMachine::LocalAuthenticationAccepted(const char *name)
281de2f76e1SWaldemar Kornewald {
28284b580c4SWaldemar Kornewald TRACE("KPPPSM: LocalAuthenticationAccepted() state=%d phase=%d\n",
2834e0ad752SWaldemar Kornewald State(), Phase());
2844e0ad752SWaldemar Kornewald
285de2f76e1SWaldemar Kornewald fLocalAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL;
286de2f76e1SWaldemar Kornewald free(fLocalAuthenticationName);
2874e0ad752SWaldemar Kornewald if (name)
288de2f76e1SWaldemar Kornewald fLocalAuthenticationName = strdup(name);
2894e0ad752SWaldemar Kornewald else
2904e0ad752SWaldemar Kornewald fLocalAuthenticationName = NULL;
291de2f76e1SWaldemar Kornewald }
292de2f76e1SWaldemar Kornewald
293de2f76e1SWaldemar Kornewald
2943f3689bbSWaldemar Kornewald /*! \brief Notification that local authentication was denied.
2953f3689bbSWaldemar Kornewald
2963f3689bbSWaldemar Kornewald NOTE: This must be called \e before \c UpFailedEvent().
2973f3689bbSWaldemar Kornewald
2983f3689bbSWaldemar Kornewald \param name The username/login that was denied.
2993f3689bbSWaldemar Kornewald */
300de2f76e1SWaldemar Kornewald void
LocalAuthenticationDenied(const char * name)301f9ad2df8SWaldemar Kornewald KPPPStateMachine::LocalAuthenticationDenied(const char *name)
302de2f76e1SWaldemar Kornewald {
30384b580c4SWaldemar Kornewald TRACE("KPPPSM: LocalAuthenticationDenied() state=%d phase=%d\n", State(), Phase());
3044e0ad752SWaldemar Kornewald
305de2f76e1SWaldemar Kornewald fLocalAuthenticationStatus = PPP_AUTHENTICATION_FAILED;
306de2f76e1SWaldemar Kornewald free(fLocalAuthenticationName);
3074e0ad752SWaldemar Kornewald if (name)
308de2f76e1SWaldemar Kornewald fLocalAuthenticationName = strdup(name);
3094e0ad752SWaldemar Kornewald else
3104e0ad752SWaldemar Kornewald fLocalAuthenticationName = NULL;
3116ff76cdaSWaldemar Kornewald
3126ff76cdaSWaldemar Kornewald // the report will be sent in DownEvent()
313de2f76e1SWaldemar Kornewald }
314de2f76e1SWaldemar Kornewald
315de2f76e1SWaldemar Kornewald
3163f3689bbSWaldemar Kornewald //! Notification that peer authentication is requested.
317de2f76e1SWaldemar Kornewald void
PeerAuthenticationRequested()318f9ad2df8SWaldemar Kornewald KPPPStateMachine::PeerAuthenticationRequested()
319de2f76e1SWaldemar Kornewald {
32084b580c4SWaldemar Kornewald TRACE("KPPPSM: PeerAuthenticationRequested() state=%d phase=%d\n",
3214e0ad752SWaldemar Kornewald State(), Phase());
3224e0ad752SWaldemar Kornewald
323abdb7d1aSWaldemar Kornewald fLastConnectionReportCode = PPP_REPORT_AUTHENTICATION_REQUESTED;
3245a483e4dSWaldemar Kornewald Interface().Report(PPP_CONNECTION_REPORT,
325abdb7d1aSWaldemar Kornewald PPP_REPORT_AUTHENTICATION_REQUESTED, &fInterface.fID,
3265a483e4dSWaldemar Kornewald sizeof(ppp_interface_id));
3275a483e4dSWaldemar Kornewald
328de2f76e1SWaldemar Kornewald fPeerAuthenticationStatus = PPP_AUTHENTICATING;
329de2f76e1SWaldemar Kornewald free(fPeerAuthenticationName);
330de2f76e1SWaldemar Kornewald fPeerAuthenticationName = NULL;
331de2f76e1SWaldemar Kornewald }
332de2f76e1SWaldemar Kornewald
333de2f76e1SWaldemar Kornewald
3343f3689bbSWaldemar Kornewald /*! \brief Notification that peer authentication was accepted.
3353f3689bbSWaldemar Kornewald
3363f3689bbSWaldemar Kornewald NOTE: This must be called \e before \c UpEvent().
3373f3689bbSWaldemar Kornewald
3383f3689bbSWaldemar Kornewald \param name The username/login that was accepted.
3393f3689bbSWaldemar Kornewald */
340de2f76e1SWaldemar Kornewald void
PeerAuthenticationAccepted(const char * name)341f9ad2df8SWaldemar Kornewald KPPPStateMachine::PeerAuthenticationAccepted(const char *name)
342de2f76e1SWaldemar Kornewald {
34384b580c4SWaldemar Kornewald TRACE("KPPPSM: PeerAuthenticationAccepted() state=%d phase=%d\n",
3444e0ad752SWaldemar Kornewald State(), Phase());
3454e0ad752SWaldemar Kornewald
346de2f76e1SWaldemar Kornewald fPeerAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL;
347de2f76e1SWaldemar Kornewald free(fPeerAuthenticationName);
3484e0ad752SWaldemar Kornewald if (name)
349de2f76e1SWaldemar Kornewald fPeerAuthenticationName = strdup(name);
3504e0ad752SWaldemar Kornewald else
3514e0ad752SWaldemar Kornewald fPeerAuthenticationName = NULL;
352de2f76e1SWaldemar Kornewald }
353de2f76e1SWaldemar Kornewald
354de2f76e1SWaldemar Kornewald
3553f3689bbSWaldemar Kornewald /*! \brief Notification that peer authentication was denied.
3563f3689bbSWaldemar Kornewald
3573f3689bbSWaldemar Kornewald NOTE: This must be called \e before \c UpFailedEvent().
3583f3689bbSWaldemar Kornewald
3593f3689bbSWaldemar Kornewald \param name The username/login that was denied.
3603f3689bbSWaldemar Kornewald */
361de2f76e1SWaldemar Kornewald void
PeerAuthenticationDenied(const char * name)362f9ad2df8SWaldemar Kornewald KPPPStateMachine::PeerAuthenticationDenied(const char *name)
363de2f76e1SWaldemar Kornewald {
36484b580c4SWaldemar Kornewald TRACE("KPPPSM: PeerAuthenticationDenied() state=%d phase=%d\n", State(), Phase());
3654e0ad752SWaldemar Kornewald
366de2f76e1SWaldemar Kornewald fPeerAuthenticationStatus = PPP_AUTHENTICATION_FAILED;
367de2f76e1SWaldemar Kornewald free(fPeerAuthenticationName);
3684e0ad752SWaldemar Kornewald if (name)
369de2f76e1SWaldemar Kornewald fPeerAuthenticationName = strdup(name);
3704e0ad752SWaldemar Kornewald else
3714e0ad752SWaldemar Kornewald fPeerAuthenticationName = NULL;
372de2f76e1SWaldemar Kornewald
373de2f76e1SWaldemar Kornewald CloseEvent();
3746ff76cdaSWaldemar Kornewald
3756ff76cdaSWaldemar Kornewald // the report will be sent in DownEvent()
376de2f76e1SWaldemar Kornewald }
377de2f76e1SWaldemar Kornewald
378de2f76e1SWaldemar Kornewald
3793f3689bbSWaldemar Kornewald //! Notification that a child interface failed to go up.
380de2f76e1SWaldemar Kornewald void
UpFailedEvent(KPPPInterface & interface)381f9ad2df8SWaldemar Kornewald KPPPStateMachine::UpFailedEvent(KPPPInterface& interface)
382de2f76e1SWaldemar Kornewald {
38384b580c4SWaldemar Kornewald TRACE("KPPPSM: UpFailedEvent(interface) state=%d phase=%d\n", State(), Phase());
3844e0ad752SWaldemar Kornewald
385de2f76e1SWaldemar Kornewald // TODO:
386de2f76e1SWaldemar Kornewald // log that an interface did not go up
387de2f76e1SWaldemar Kornewald }
388de2f76e1SWaldemar Kornewald
389de2f76e1SWaldemar Kornewald
3903f3689bbSWaldemar Kornewald //! Notification that a child interface went up successfully.
391de2f76e1SWaldemar Kornewald void
UpEvent(KPPPInterface & interface)392f9ad2df8SWaldemar Kornewald KPPPStateMachine::UpEvent(KPPPInterface& interface)
393de2f76e1SWaldemar Kornewald {
39484b580c4SWaldemar Kornewald TRACE("KPPPSM: UpEvent(interface) state=%d phase=%d\n", State(), Phase());
3954e0ad752SWaldemar Kornewald
396de2f76e1SWaldemar Kornewald if (Phase() <= PPP_TERMINATION_PHASE) {
397de2f76e1SWaldemar Kornewald interface.StateMachine().CloseEvent();
398de2f76e1SWaldemar Kornewald return;
399de2f76e1SWaldemar Kornewald }
400de2f76e1SWaldemar Kornewald
401de2f76e1SWaldemar Kornewald Interface().CalculateBaudRate();
402de2f76e1SWaldemar Kornewald
403de2f76e1SWaldemar Kornewald if (Phase() == PPP_ESTABLISHMENT_PHASE) {
404de2f76e1SWaldemar Kornewald // this is the first interface that went up
405de2f76e1SWaldemar Kornewald Interface().SetMRU(interface.MRU());
406de2f76e1SWaldemar Kornewald ThisLayerUp();
407de2f76e1SWaldemar Kornewald } else if (Interface().MRU() > interface.MRU())
408de2f76e1SWaldemar Kornewald Interface().SetMRU(interface.MRU());
409de2f76e1SWaldemar Kornewald // MRU should always be the smallest value of all children
410de2f76e1SWaldemar Kornewald
411de2f76e1SWaldemar Kornewald NewState(PPP_OPENED_STATE);
412de2f76e1SWaldemar Kornewald }
413de2f76e1SWaldemar Kornewald
414de2f76e1SWaldemar Kornewald
4153f3689bbSWaldemar Kornewald //! Notification that a child interface went down.
416de2f76e1SWaldemar Kornewald void
DownEvent(KPPPInterface & interface)417f9ad2df8SWaldemar Kornewald KPPPStateMachine::DownEvent(KPPPInterface& interface)
418de2f76e1SWaldemar Kornewald {
41984b580c4SWaldemar Kornewald TRACE("KPPPSM: DownEvent(interface) state=%d phase=%d\n", State(), Phase());
4204e0ad752SWaldemar Kornewald
421de2f76e1SWaldemar Kornewald uint32 MRU = 0;
422de2f76e1SWaldemar Kornewald // the new MRU
423de2f76e1SWaldemar Kornewald
424de2f76e1SWaldemar Kornewald Interface().CalculateBaudRate();
425de2f76e1SWaldemar Kornewald
426de2f76e1SWaldemar Kornewald // when all children are down we should not be running
427de2f76e1SWaldemar Kornewald if (Interface().IsMultilink() && !Interface().Parent()) {
428de2f76e1SWaldemar Kornewald uint32 count = 0;
429f9ad2df8SWaldemar Kornewald KPPPInterface *child;
430de2f76e1SWaldemar Kornewald for (int32 index = 0; index < Interface().CountChildren(); index++) {
431de2f76e1SWaldemar Kornewald child = Interface().ChildAt(index);
432de2f76e1SWaldemar Kornewald
433de2f76e1SWaldemar Kornewald if (child && child->IsUp()) {
434de2f76e1SWaldemar Kornewald // set MRU to the smallest value of all children
435de2f76e1SWaldemar Kornewald if (MRU == 0)
436de2f76e1SWaldemar Kornewald MRU = child->MRU();
437de2f76e1SWaldemar Kornewald else if (MRU > child->MRU())
438de2f76e1SWaldemar Kornewald MRU = child->MRU();
439de2f76e1SWaldemar Kornewald
440de2f76e1SWaldemar Kornewald ++count;
441de2f76e1SWaldemar Kornewald }
442de2f76e1SWaldemar Kornewald }
443de2f76e1SWaldemar Kornewald
444de2f76e1SWaldemar Kornewald if (MRU == 0)
445de2f76e1SWaldemar Kornewald Interface().SetMRU(1500);
446de2f76e1SWaldemar Kornewald else
447de2f76e1SWaldemar Kornewald Interface().SetMRU(MRU);
448de2f76e1SWaldemar Kornewald
4492f13f213SWaldemar Kornewald if (count == 0)
450de2f76e1SWaldemar Kornewald DownEvent();
451de2f76e1SWaldemar Kornewald }
452de2f76e1SWaldemar Kornewald }
453de2f76e1SWaldemar Kornewald
454de2f76e1SWaldemar Kornewald
4553f3689bbSWaldemar Kornewald /*! \brief Notification that a protocol failed to go up.
4563f3689bbSWaldemar Kornewald
4573f3689bbSWaldemar Kornewald NOTE FOR AUTHENTICATORS: This \e must be called \e after an authentication
4583f3689bbSWaldemar Kornewald notification method like \c LocalAuthenticationFailed().
4593f3689bbSWaldemar Kornewald */
460de2f76e1SWaldemar Kornewald void
UpFailedEvent(KPPPProtocol * protocol)461f9ad2df8SWaldemar Kornewald KPPPStateMachine::UpFailedEvent(KPPPProtocol *protocol)
462de2f76e1SWaldemar Kornewald {
46384b580c4SWaldemar Kornewald TRACE("KPPPSM: UpFailedEvent(protocol) state=%d phase=%d\n", State(), Phase());
4644e0ad752SWaldemar Kornewald
465de2f76e1SWaldemar Kornewald if ((protocol->Flags() & PPP_NOT_IMPORTANT) == 0) {
466de2f76e1SWaldemar Kornewald if (Interface().Mode() == PPP_CLIENT_MODE) {
46792a8026eSWaldemar Kornewald // pretend we lost connection
468de2f76e1SWaldemar Kornewald if (Interface().IsMultilink() && !Interface().Parent())
469de2f76e1SWaldemar Kornewald for (int32 index = 0; index < Interface().CountChildren(); index++)
470de2f76e1SWaldemar Kornewald Interface().ChildAt(index)->StateMachine().CloseEvent();
471de2f76e1SWaldemar Kornewald else if (Interface().Device())
472de2f76e1SWaldemar Kornewald Interface().Device()->Down();
473de2f76e1SWaldemar Kornewald else
474de2f76e1SWaldemar Kornewald CloseEvent();
475de2f76e1SWaldemar Kornewald // just to be on the secure side ;)
476de2f76e1SWaldemar Kornewald } else
477de2f76e1SWaldemar Kornewald CloseEvent();
478de2f76e1SWaldemar Kornewald }
479de2f76e1SWaldemar Kornewald }
480de2f76e1SWaldemar Kornewald
481de2f76e1SWaldemar Kornewald
4823f3689bbSWaldemar Kornewald /*! \brief Notification that a protocol went up successfully.
4833f3689bbSWaldemar Kornewald
4843f3689bbSWaldemar Kornewald NOTE FOR AUTHENTICATORS: This \e must be called \e after an authentication
4853f3689bbSWaldemar Kornewald notification method like \c LocalAuthenticationSuccessful().
4863f3689bbSWaldemar Kornewald */
487de2f76e1SWaldemar Kornewald void
UpEvent(KPPPProtocol * protocol)488f9ad2df8SWaldemar Kornewald KPPPStateMachine::UpEvent(KPPPProtocol *protocol)
489de2f76e1SWaldemar Kornewald {
49084b580c4SWaldemar Kornewald TRACE("KPPPSM: UpEvent(protocol) state=%d phase=%d\n", State(), Phase());
4914e0ad752SWaldemar Kornewald
492de2f76e1SWaldemar Kornewald if (Phase() >= PPP_ESTABLISHMENT_PHASE)
49392a8026eSWaldemar Kornewald BringProtocolsUp();
494de2f76e1SWaldemar Kornewald }
495de2f76e1SWaldemar Kornewald
496de2f76e1SWaldemar Kornewald
4973f3689bbSWaldemar Kornewald /*! \brief Notification that a protocol went down.
4983f3689bbSWaldemar Kornewald
4993f3689bbSWaldemar Kornewald NOTE FOR AUTHENTICATORS: This \e must be called \e after an authentication
5003f3689bbSWaldemar Kornewald notification method like \c LocalAuthenticationFailed().
5013f3689bbSWaldemar Kornewald */
502de2f76e1SWaldemar Kornewald void
DownEvent(KPPPProtocol * protocol)503f9ad2df8SWaldemar Kornewald KPPPStateMachine::DownEvent(KPPPProtocol *protocol)
504de2f76e1SWaldemar Kornewald {
50584b580c4SWaldemar Kornewald TRACE("KPPPSM: DownEvent(protocol) state=%d phase=%d\n", State(), Phase());
506de2f76e1SWaldemar Kornewald }
507de2f76e1SWaldemar Kornewald
508de2f76e1SWaldemar Kornewald
5093f3689bbSWaldemar Kornewald /*! \brief Notification that the device entered establishment phase.
5103f3689bbSWaldemar Kornewald
5113f3689bbSWaldemar Kornewald We can use \c Device::Down() to abort establishment until \c UpEvent() is called.
5123f3689bbSWaldemar Kornewald
5133f3689bbSWaldemar Kornewald \return
5143f3689bbSWaldemar Kornewald - \c true: We are waiting for an \c UpEvent()
5153f3689bbSWaldemar Kornewald - \c false: The device should immediately abort its attempt to connect.
5163f3689bbSWaldemar Kornewald */
517de2f76e1SWaldemar Kornewald bool
TLSNotify()518f9ad2df8SWaldemar Kornewald KPPPStateMachine::TLSNotify()
519de2f76e1SWaldemar Kornewald {
52084b580c4SWaldemar Kornewald TRACE("KPPPSM: TLSNotify() state=%d phase=%d\n", State(), Phase());
5214e0ad752SWaldemar Kornewald
522de2f76e1SWaldemar Kornewald if (State() == PPP_STARTING_STATE) {
523de2f76e1SWaldemar Kornewald if (Phase() == PPP_DOWN_PHASE)
524de2f76e1SWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
525de2f76e1SWaldemar Kornewald // this says that the device is going up
526de2f76e1SWaldemar Kornewald return true;
527de2f76e1SWaldemar Kornewald }
528de2f76e1SWaldemar Kornewald
529de2f76e1SWaldemar Kornewald return false;
530de2f76e1SWaldemar Kornewald }
531de2f76e1SWaldemar Kornewald
532de2f76e1SWaldemar Kornewald
5333f3689bbSWaldemar Kornewald /*! \brief Notification that the device entered termination phase.
5343f3689bbSWaldemar Kornewald
5353f3689bbSWaldemar Kornewald A \c Device::Up() should wait until the device went down.
5363f3689bbSWaldemar Kornewald
5373f3689bbSWaldemar Kornewald \return
5383f3689bbSWaldemar Kornewald - \c true: Continue terminating.
5393f3689bbSWaldemar Kornewald - \c false: We want to stay connected, though we called \c Device::Down().
5403f3689bbSWaldemar Kornewald */
541de2f76e1SWaldemar Kornewald bool
TLFNotify()542f9ad2df8SWaldemar Kornewald KPPPStateMachine::TLFNotify()
543de2f76e1SWaldemar Kornewald {
54484b580c4SWaldemar Kornewald TRACE("KPPPSM: TLFNotify() state=%d phase=%d\n", State(), Phase());
5454e0ad752SWaldemar Kornewald
5464e0ad752SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
5474e0ad752SWaldemar Kornewald // tell DownEvent() that it may create a connection-lost-report
548de2f76e1SWaldemar Kornewald
549de2f76e1SWaldemar Kornewald return true;
550de2f76e1SWaldemar Kornewald }
551de2f76e1SWaldemar Kornewald
552de2f76e1SWaldemar Kornewald
5533f3689bbSWaldemar Kornewald //! Notification that the device failed to go up.
554de2f76e1SWaldemar Kornewald void
UpFailedEvent()555f9ad2df8SWaldemar Kornewald KPPPStateMachine::UpFailedEvent()
556de2f76e1SWaldemar Kornewald {
55784b580c4SWaldemar Kornewald TRACE("KPPPSM: UpFailedEvent() state=%d phase=%d\n", State(), Phase());
5584e0ad752SWaldemar Kornewald
559de2f76e1SWaldemar Kornewald switch (State()) {
560de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
561abdb7d1aSWaldemar Kornewald fLastConnectionReportCode = PPP_REPORT_DEVICE_UP_FAILED;
562de2f76e1SWaldemar Kornewald Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_DEVICE_UP_FAILED,
5636cfb4dcaSWaldemar Kornewald &fInterface.fID, sizeof(ppp_interface_id));
564de2f76e1SWaldemar Kornewald if (Interface().Parent())
565de2f76e1SWaldemar Kornewald Interface().Parent()->StateMachine().UpFailedEvent(Interface());
566e7452421SWaldemar Kornewald
567e7452421SWaldemar Kornewald NewPhase(PPP_DOWN_PHASE);
568b0bff411SWaldemar Kornewald // tell DownEvent() that it should not create a connection-lost-report
569e7452421SWaldemar Kornewald DownEvent();
570de2f76e1SWaldemar Kornewald break;
571de2f76e1SWaldemar Kornewald
572de2f76e1SWaldemar Kornewald default:
573de2f76e1SWaldemar Kornewald IllegalEvent(PPP_UP_FAILED_EVENT);
574de2f76e1SWaldemar Kornewald }
575de2f76e1SWaldemar Kornewald }
576de2f76e1SWaldemar Kornewald
577de2f76e1SWaldemar Kornewald
5783f3689bbSWaldemar Kornewald //! Notification that the device went up successfully.
579de2f76e1SWaldemar Kornewald void
UpEvent()580f9ad2df8SWaldemar Kornewald KPPPStateMachine::UpEvent()
581de2f76e1SWaldemar Kornewald {
58284b580c4SWaldemar Kornewald TRACE("KPPPSM: UpEvent() state=%d phase=%d\n", State(), Phase());
5834e0ad752SWaldemar Kornewald
584de2f76e1SWaldemar Kornewald // This call is public, thus, it might not only be called by the device.
585de2f76e1SWaldemar Kornewald // We must recognize these attempts to fool us and handle them correctly.
586de2f76e1SWaldemar Kornewald
587de2f76e1SWaldemar Kornewald if (!Interface().Device() || !Interface().Device()->IsUp())
588de2f76e1SWaldemar Kornewald return;
589de2f76e1SWaldemar Kornewald // it is not our device that went up...
590de2f76e1SWaldemar Kornewald
591de2f76e1SWaldemar Kornewald Interface().CalculateBaudRate();
592de2f76e1SWaldemar Kornewald
593de2f76e1SWaldemar Kornewald switch (State()) {
594de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
595de2f76e1SWaldemar Kornewald if (Interface().Mode() != PPP_SERVER_MODE
596de2f76e1SWaldemar Kornewald || Phase() != PPP_ESTABLISHMENT_PHASE) {
597de2f76e1SWaldemar Kornewald // we are a client or we do not listen for an incoming
598de2f76e1SWaldemar Kornewald // connection, so this is an illegal event
599de2f76e1SWaldemar Kornewald IllegalEvent(PPP_UP_EVENT);
600de2f76e1SWaldemar Kornewald NewState(PPP_CLOSED_STATE);
601de2f76e1SWaldemar Kornewald ThisLayerFinished();
602de2f76e1SWaldemar Kornewald
603de2f76e1SWaldemar Kornewald return;
604de2f76e1SWaldemar Kornewald }
605de2f76e1SWaldemar Kornewald
606de2f76e1SWaldemar Kornewald // TODO: handle server-up! (maybe already done correctly)
607de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
608de2f76e1SWaldemar Kornewald InitializeRestartCount();
609de2f76e1SWaldemar Kornewald SendConfigureRequest();
610de2f76e1SWaldemar Kornewald break;
611de2f76e1SWaldemar Kornewald
612de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
613de2f76e1SWaldemar Kornewald // we must have called TLS() which sets establishment phase
614de2f76e1SWaldemar Kornewald if (Phase() != PPP_ESTABLISHMENT_PHASE) {
615de2f76e1SWaldemar Kornewald // there must be a BUG in the device add-on or someone is trying to
616de2f76e1SWaldemar Kornewald // fool us (UpEvent() is public) as we did not request the device
617de2f76e1SWaldemar Kornewald // to go up
618de2f76e1SWaldemar Kornewald IllegalEvent(PPP_UP_EVENT);
619de2f76e1SWaldemar Kornewald NewState(PPP_CLOSED_STATE);
620de2f76e1SWaldemar Kornewald ThisLayerFinished();
621de2f76e1SWaldemar Kornewald break;
622de2f76e1SWaldemar Kornewald }
623de2f76e1SWaldemar Kornewald
624de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
625de2f76e1SWaldemar Kornewald InitializeRestartCount();
626de2f76e1SWaldemar Kornewald SendConfigureRequest();
627de2f76e1SWaldemar Kornewald break;
628de2f76e1SWaldemar Kornewald
629de2f76e1SWaldemar Kornewald default:
630de2f76e1SWaldemar Kornewald IllegalEvent(PPP_UP_EVENT);
631de2f76e1SWaldemar Kornewald }
632de2f76e1SWaldemar Kornewald }
633de2f76e1SWaldemar Kornewald
634de2f76e1SWaldemar Kornewald
6353f3689bbSWaldemar Kornewald /*! \brief Notification that the device went down.
6363f3689bbSWaldemar Kornewald
6373f3689bbSWaldemar Kornewald If this is called without a prior \c TLFNotify() the state machine will assume
6383f3689bbSWaldemar Kornewald that we lost our connection.
6393f3689bbSWaldemar Kornewald */
640de2f76e1SWaldemar Kornewald void
DownEvent()641f9ad2df8SWaldemar Kornewald KPPPStateMachine::DownEvent()
642de2f76e1SWaldemar Kornewald {
64384b580c4SWaldemar Kornewald TRACE("KPPPSM: DownEvent() state=%d phase=%d\n", State(), Phase());
6444e0ad752SWaldemar Kornewald
645de2f76e1SWaldemar Kornewald if (Interface().Device() && Interface().Device()->IsUp())
646de2f76e1SWaldemar Kornewald return;
6475a483e4dSWaldemar Kornewald // it is not our device that went down...
648de2f76e1SWaldemar Kornewald
649de2f76e1SWaldemar Kornewald Interface().CalculateBaudRate();
650de2f76e1SWaldemar Kornewald
651de2f76e1SWaldemar Kornewald // reset IdleSince
652de2f76e1SWaldemar Kornewald Interface().fIdleSince = 0;
653de2f76e1SWaldemar Kornewald
654de2f76e1SWaldemar Kornewald switch (State()) {
6554e0ad752SWaldemar Kornewald // XXX: this does not belong to the standard, but may happen in our
6564e0ad752SWaldemar Kornewald // implementation
6574e0ad752SWaldemar Kornewald case PPP_STARTING_STATE:
6584e0ad752SWaldemar Kornewald break;
6594e0ad752SWaldemar Kornewald
660de2f76e1SWaldemar Kornewald case PPP_CLOSED_STATE:
661de2f76e1SWaldemar Kornewald case PPP_CLOSING_STATE:
662de2f76e1SWaldemar Kornewald NewState(PPP_INITIAL_STATE);
663de2f76e1SWaldemar Kornewald break;
664de2f76e1SWaldemar Kornewald
665de2f76e1SWaldemar Kornewald case PPP_STOPPED_STATE:
666de2f76e1SWaldemar Kornewald // The RFC says we should reconnect, but our implementation
6670cbb739dSWaldemar Kornewald // will only do this if auto-reconnect is enabled (only clients).
668de2f76e1SWaldemar Kornewald NewState(PPP_STARTING_STATE);
669de2f76e1SWaldemar Kornewald break;
670de2f76e1SWaldemar Kornewald
671de2f76e1SWaldemar Kornewald case PPP_STOPPING_STATE:
672de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
673de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
674de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
675de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
676de2f76e1SWaldemar Kornewald NewState(PPP_STARTING_STATE);
677de2f76e1SWaldemar Kornewald break;
678de2f76e1SWaldemar Kornewald
679de2f76e1SWaldemar Kornewald default:
680de2f76e1SWaldemar Kornewald IllegalEvent(PPP_DOWN_EVENT);
681de2f76e1SWaldemar Kornewald }
682de2f76e1SWaldemar Kornewald
683e7452421SWaldemar Kornewald ppp_phase oldPhase = Phase();
684de2f76e1SWaldemar Kornewald NewPhase(PPP_DOWN_PHASE);
685de2f76e1SWaldemar Kornewald
686de2f76e1SWaldemar Kornewald DownProtocols();
687de2f76e1SWaldemar Kornewald
6880cbb739dSWaldemar Kornewald // maybe we need to reconnect
689de2f76e1SWaldemar Kornewald if (State() == PPP_STARTING_STATE) {
690abdb7d1aSWaldemar Kornewald bool deleteInterface = false, retry = false;
691de2f76e1SWaldemar Kornewald
6920cbb739dSWaldemar Kornewald // we do not try to reconnect if authentication failed
693de2f76e1SWaldemar Kornewald if (fLocalAuthenticationStatus == PPP_AUTHENTICATION_FAILED
694abdb7d1aSWaldemar Kornewald || fLocalAuthenticationStatus == PPP_AUTHENTICATING
695abdb7d1aSWaldemar Kornewald || fPeerAuthenticationStatus == PPP_AUTHENTICATION_FAILED
696abdb7d1aSWaldemar Kornewald || fPeerAuthenticationStatus == PPP_AUTHENTICATING) {
697abdb7d1aSWaldemar Kornewald fLastConnectionReportCode = PPP_REPORT_AUTHENTICATION_FAILED;
698de2f76e1SWaldemar Kornewald Interface().Report(PPP_CONNECTION_REPORT,
699abdb7d1aSWaldemar Kornewald PPP_REPORT_AUTHENTICATION_FAILED, &fInterface.fID,
7006cfb4dcaSWaldemar Kornewald sizeof(ppp_interface_id));
701abdb7d1aSWaldemar Kornewald deleteInterface = true;
702abdb7d1aSWaldemar Kornewald } else {
703abdb7d1aSWaldemar Kornewald if (Interface().fConnectAttempt > (Interface().fConnectRetriesLimit + 1))
704abdb7d1aSWaldemar Kornewald deleteInterface = true;
705de2f76e1SWaldemar Kornewald
706abdb7d1aSWaldemar Kornewald if (oldPhase == PPP_DOWN_PHASE) {
707abdb7d1aSWaldemar Kornewald // failed to bring device up (UpFailedEvent() was called)
708abdb7d1aSWaldemar Kornewald retry = true;
709abdb7d1aSWaldemar Kornewald // this may have been overridden by "deleteInterface = true"
710abdb7d1aSWaldemar Kornewald } else {
711abdb7d1aSWaldemar Kornewald // lost connection (TLFNotify() was called)
712abdb7d1aSWaldemar Kornewald fLastConnectionReportCode = PPP_REPORT_CONNECTION_LOST;
713de2f76e1SWaldemar Kornewald Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_CONNECTION_LOST,
7146cfb4dcaSWaldemar Kornewald &fInterface.fID, sizeof(ppp_interface_id));
715de2f76e1SWaldemar Kornewald }
716abdb7d1aSWaldemar Kornewald }
717de2f76e1SWaldemar Kornewald
718de2f76e1SWaldemar Kornewald if (Interface().Parent())
719de2f76e1SWaldemar Kornewald Interface().Parent()->StateMachine().UpFailedEvent(Interface());
720de2f76e1SWaldemar Kornewald
721de2f76e1SWaldemar Kornewald NewState(PPP_INITIAL_STATE);
722de2f76e1SWaldemar Kornewald
723abdb7d1aSWaldemar Kornewald if (!deleteInterface && (retry || Interface().DoesAutoReconnect()))
7240cbb739dSWaldemar Kornewald Interface().Reconnect(Interface().ReconnectDelay());
725abdb7d1aSWaldemar Kornewald else
726de2f76e1SWaldemar Kornewald Interface().Delete();
727de2f76e1SWaldemar Kornewald } else {
728abdb7d1aSWaldemar Kornewald fLastConnectionReportCode = PPP_REPORT_DOWN_SUCCESSFUL;
72949c2f687SWaldemar Kornewald Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_DOWN_SUCCESSFUL,
7306cfb4dcaSWaldemar Kornewald &fInterface.fID, sizeof(ppp_interface_id));
731de2f76e1SWaldemar Kornewald Interface().Delete();
732de2f76e1SWaldemar Kornewald }
733ce0b86e9SWaldemar Kornewald
734ce0b86e9SWaldemar Kornewald fLocalAuthenticationStatus = PPP_NOT_AUTHENTICATED;
735ce0b86e9SWaldemar Kornewald fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED;
736de2f76e1SWaldemar Kornewald }
737de2f76e1SWaldemar Kornewald
738de2f76e1SWaldemar Kornewald
739de2f76e1SWaldemar Kornewald // private events
740de2f76e1SWaldemar Kornewald void
OpenEvent()741f9ad2df8SWaldemar Kornewald KPPPStateMachine::OpenEvent()
742de2f76e1SWaldemar Kornewald {
74384b580c4SWaldemar Kornewald TRACE("KPPPSM: OpenEvent() state=%d phase=%d\n", State(), Phase());
7444e0ad752SWaldemar Kornewald
7454e0ad752SWaldemar Kornewald // reset all handlers
746ca43389aSWaldemar Kornewald if (Phase() != PPP_ESTABLISHED_PHASE) {
7474e0ad752SWaldemar Kornewald DownProtocols();
7484e0ad752SWaldemar Kornewald ResetLCPHandlers();
749ca43389aSWaldemar Kornewald }
7504e0ad752SWaldemar Kornewald
751de2f76e1SWaldemar Kornewald switch (State()) {
752de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
753abdb7d1aSWaldemar Kornewald fLastConnectionReportCode = PPP_REPORT_GOING_UP;
754abdb7d1aSWaldemar Kornewald Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_GOING_UP,
755a89ad654SWaldemar Kornewald &fInterface.fID, sizeof(ppp_interface_id));
756de2f76e1SWaldemar Kornewald
757de2f76e1SWaldemar Kornewald if (Interface().Mode() == PPP_SERVER_MODE) {
758de2f76e1SWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
759de2f76e1SWaldemar Kornewald
760e7452421SWaldemar Kornewald if (Interface().Device() && !Interface().Device()->Up()) {
761e7452421SWaldemar Kornewald Interface().Device()->UpFailedEvent();
762e7452421SWaldemar Kornewald return;
763e7452421SWaldemar Kornewald }
764de2f76e1SWaldemar Kornewald } else
765de2f76e1SWaldemar Kornewald NewState(PPP_STARTING_STATE);
766de2f76e1SWaldemar Kornewald
7672f13f213SWaldemar Kornewald if (Interface().fAskBeforeConnecting == false)
768abdb7d1aSWaldemar Kornewald ContinueOpenEvent();
769de2f76e1SWaldemar Kornewald break;
770de2f76e1SWaldemar Kornewald
771de2f76e1SWaldemar Kornewald case PPP_CLOSED_STATE:
772de2f76e1SWaldemar Kornewald if (Phase() == PPP_DOWN_PHASE) {
773de2f76e1SWaldemar Kornewald // the device is already going down
774de2f76e1SWaldemar Kornewald return;
775de2f76e1SWaldemar Kornewald }
776de2f76e1SWaldemar Kornewald
777de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
778de2f76e1SWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
779de2f76e1SWaldemar Kornewald InitializeRestartCount();
780de2f76e1SWaldemar Kornewald SendConfigureRequest();
781de2f76e1SWaldemar Kornewald break;
782de2f76e1SWaldemar Kornewald
783de2f76e1SWaldemar Kornewald case PPP_CLOSING_STATE:
784de2f76e1SWaldemar Kornewald NewState(PPP_STOPPING_STATE);
785de2f76e1SWaldemar Kornewald break;
786de2f76e1SWaldemar Kornewald
787de2f76e1SWaldemar Kornewald default:
788de2f76e1SWaldemar Kornewald ;
789de2f76e1SWaldemar Kornewald }
790de2f76e1SWaldemar Kornewald }
791de2f76e1SWaldemar Kornewald
792de2f76e1SWaldemar Kornewald
793de2f76e1SWaldemar Kornewald void
ContinueOpenEvent()794abdb7d1aSWaldemar Kornewald KPPPStateMachine::ContinueOpenEvent()
795abdb7d1aSWaldemar Kornewald {
796abdb7d1aSWaldemar Kornewald TRACE("KPPPSM: ContinueOpenEvent() state=%d phase=%d\n", State(), Phase());
797abdb7d1aSWaldemar Kornewald
798abdb7d1aSWaldemar Kornewald if (Interface().IsMultilink() && !Interface().Parent()) {
799abdb7d1aSWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
800abdb7d1aSWaldemar Kornewald for (int32 index = 0; index < Interface().CountChildren(); index++)
801abdb7d1aSWaldemar Kornewald if (Interface().ChildAt(index)->Mode() == Interface().Mode())
802abdb7d1aSWaldemar Kornewald Interface().ChildAt(index)->StateMachine().OpenEvent();
803abdb7d1aSWaldemar Kornewald } else
804abdb7d1aSWaldemar Kornewald ThisLayerStarted();
805abdb7d1aSWaldemar Kornewald }
806abdb7d1aSWaldemar Kornewald
807abdb7d1aSWaldemar Kornewald
808abdb7d1aSWaldemar Kornewald void
CloseEvent()809f9ad2df8SWaldemar Kornewald KPPPStateMachine::CloseEvent()
810de2f76e1SWaldemar Kornewald {
81184b580c4SWaldemar Kornewald TRACE("KPPPSM: CloseEvent() state=%d phase=%d\n", State(), Phase());
8124e0ad752SWaldemar Kornewald
813de2f76e1SWaldemar Kornewald if (Interface().IsMultilink() && !Interface().Parent()) {
814de2f76e1SWaldemar Kornewald NewState(PPP_INITIAL_STATE);
815de2f76e1SWaldemar Kornewald
816de2f76e1SWaldemar Kornewald if (Phase() != PPP_DOWN_PHASE)
817de2f76e1SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
818de2f76e1SWaldemar Kornewald
819de2f76e1SWaldemar Kornewald ThisLayerDown();
820de2f76e1SWaldemar Kornewald
821de2f76e1SWaldemar Kornewald for (int32 index = 0; index < Interface().CountChildren(); index++)
822de2f76e1SWaldemar Kornewald Interface().ChildAt(index)->StateMachine().CloseEvent();
823de2f76e1SWaldemar Kornewald
824de2f76e1SWaldemar Kornewald return;
825de2f76e1SWaldemar Kornewald }
826de2f76e1SWaldemar Kornewald
827de2f76e1SWaldemar Kornewald switch (State()) {
828de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
829de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
830de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
831de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
832de2f76e1SWaldemar Kornewald NewState(PPP_CLOSING_STATE);
833de2f76e1SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
834de2f76e1SWaldemar Kornewald // indicates to handlers that we are terminating
835de2f76e1SWaldemar Kornewald InitializeRestartCount();
836de2f76e1SWaldemar Kornewald if (State() == PPP_OPENED_STATE)
837de2f76e1SWaldemar Kornewald ThisLayerDown();
838de2f76e1SWaldemar Kornewald SendTerminateRequest();
839de2f76e1SWaldemar Kornewald break;
840de2f76e1SWaldemar Kornewald
841de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
842de2f76e1SWaldemar Kornewald NewState(PPP_INITIAL_STATE);
843de2f76e1SWaldemar Kornewald
844de2f76e1SWaldemar Kornewald // TLSNotify() will know that we were faster because we
845de2f76e1SWaldemar Kornewald // are in PPP_INITIAL_STATE now
846de2f76e1SWaldemar Kornewald if (Phase() == PPP_ESTABLISHMENT_PHASE) {
847de2f76e1SWaldemar Kornewald // the device is already up
848de2f76e1SWaldemar Kornewald NewPhase(PPP_DOWN_PHASE);
849de2f76e1SWaldemar Kornewald // this says the following DownEvent() was not caused by
850de2f76e1SWaldemar Kornewald // a connection fault
851de2f76e1SWaldemar Kornewald ThisLayerFinished();
852de2f76e1SWaldemar Kornewald }
853de2f76e1SWaldemar Kornewald break;
854de2f76e1SWaldemar Kornewald
855de2f76e1SWaldemar Kornewald case PPP_STOPPING_STATE:
856de2f76e1SWaldemar Kornewald NewState(PPP_CLOSING_STATE);
857de2f76e1SWaldemar Kornewald break;
858de2f76e1SWaldemar Kornewald
859de2f76e1SWaldemar Kornewald case PPP_STOPPED_STATE:
860de2f76e1SWaldemar Kornewald NewState(PPP_STOPPED_STATE);
861de2f76e1SWaldemar Kornewald break;
862de2f76e1SWaldemar Kornewald
863de2f76e1SWaldemar Kornewald default:
864de2f76e1SWaldemar Kornewald ;
865de2f76e1SWaldemar Kornewald }
866de2f76e1SWaldemar Kornewald }
867de2f76e1SWaldemar Kornewald
868de2f76e1SWaldemar Kornewald
869de2f76e1SWaldemar Kornewald // timeout (restart counters are > 0)
870de2f76e1SWaldemar Kornewald void
TOGoodEvent()871f9ad2df8SWaldemar Kornewald KPPPStateMachine::TOGoodEvent()
872de2f76e1SWaldemar Kornewald {
87384b580c4SWaldemar Kornewald TRACE("KPPPSM: TOGoodEvent() state=%d phase=%d\n", State(), Phase());
8744e0ad752SWaldemar Kornewald
875de2f76e1SWaldemar Kornewald switch (State()) {
876de2f76e1SWaldemar Kornewald case PPP_CLOSING_STATE:
877de2f76e1SWaldemar Kornewald case PPP_STOPPING_STATE:
878de2f76e1SWaldemar Kornewald SendTerminateRequest();
879de2f76e1SWaldemar Kornewald break;
880de2f76e1SWaldemar Kornewald
881de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
882de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
883de2f76e1SWaldemar Kornewald
884de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
885de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
886de2f76e1SWaldemar Kornewald SendConfigureRequest();
887de2f76e1SWaldemar Kornewald break;
888de2f76e1SWaldemar Kornewald
889de2f76e1SWaldemar Kornewald default:
890de2f76e1SWaldemar Kornewald IllegalEvent(PPP_TO_GOOD_EVENT);
891de2f76e1SWaldemar Kornewald }
892de2f76e1SWaldemar Kornewald }
893de2f76e1SWaldemar Kornewald
894de2f76e1SWaldemar Kornewald
895de2f76e1SWaldemar Kornewald // timeout (restart counters are <= 0)
896de2f76e1SWaldemar Kornewald void
TOBadEvent()897f9ad2df8SWaldemar Kornewald KPPPStateMachine::TOBadEvent()
898de2f76e1SWaldemar Kornewald {
89984b580c4SWaldemar Kornewald TRACE("KPPPSM: TOBadEvent() state=%d phase=%d\n", State(), Phase());
9004e0ad752SWaldemar Kornewald
901de2f76e1SWaldemar Kornewald switch (State()) {
902de2f76e1SWaldemar Kornewald case PPP_CLOSING_STATE:
903de2f76e1SWaldemar Kornewald NewState(PPP_CLOSED_STATE);
904de2f76e1SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
905de2f76e1SWaldemar Kornewald ThisLayerFinished();
906de2f76e1SWaldemar Kornewald break;
907de2f76e1SWaldemar Kornewald
908de2f76e1SWaldemar Kornewald case PPP_STOPPING_STATE:
909de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
910de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
911de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
912de2f76e1SWaldemar Kornewald NewState(PPP_STOPPED_STATE);
913de2f76e1SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
914de2f76e1SWaldemar Kornewald ThisLayerFinished();
915de2f76e1SWaldemar Kornewald break;
916de2f76e1SWaldemar Kornewald
917de2f76e1SWaldemar Kornewald default:
918de2f76e1SWaldemar Kornewald IllegalEvent(PPP_TO_BAD_EVENT);
919de2f76e1SWaldemar Kornewald }
920de2f76e1SWaldemar Kornewald }
921de2f76e1SWaldemar Kornewald
922de2f76e1SWaldemar Kornewald
923de2f76e1SWaldemar Kornewald // receive configure request (acceptable request)
924de2f76e1SWaldemar Kornewald void
RCRGoodEvent(net_buffer * packet)925e3724c38Smshlyn KPPPStateMachine::RCRGoodEvent(net_buffer *packet)
926de2f76e1SWaldemar Kornewald {
92784b580c4SWaldemar Kornewald TRACE("KPPPSM: RCRGoodEvent() state=%d phase=%d\n", State(), Phase());
9284e0ad752SWaldemar Kornewald
929de2f76e1SWaldemar Kornewald switch (State()) {
930de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
931de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
932e3724c38Smshlyn TRACE("%s::%s: PPP_STARTING_STATE\n", __FILE__, __func__);
933de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RCR_GOOD_EVENT);
934e3724c38Smshlyn gBufferModule->free(packet);
935de2f76e1SWaldemar Kornewald break;
936de2f76e1SWaldemar Kornewald
937de2f76e1SWaldemar Kornewald case PPP_CLOSED_STATE:
938e3724c38Smshlyn TRACE("%s::%s: PPP_CLOSED_STATE\n", __FILE__, __func__);
939de2f76e1SWaldemar Kornewald SendTerminateAck();
940e3724c38Smshlyn gBufferModule->free(packet);
941de2f76e1SWaldemar Kornewald break;
942de2f76e1SWaldemar Kornewald
943de2f76e1SWaldemar Kornewald case PPP_STOPPED_STATE:
944e3724c38Smshlyn TRACE("%s::%s: PPP_STOPPED_STATE\n", __FILE__, __func__);
945de2f76e1SWaldemar Kornewald // irc,scr,sca/8
946de2f76e1SWaldemar Kornewald // XXX: should we do nothing and wait for DownEvent()?
947e3724c38Smshlyn gBufferModule->free(packet);
948de2f76e1SWaldemar Kornewald break;
949de2f76e1SWaldemar Kornewald
950de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
951de2f76e1SWaldemar Kornewald NewState(PPP_ACK_SENT_STATE);
952de2f76e1SWaldemar Kornewald
953de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
954e3724c38Smshlyn TRACE("%s::%s: PPP_ACK_SENT_STATE size %ld\n", __FILE__, __func__,
955e3724c38Smshlyn packet->size);
956de2f76e1SWaldemar Kornewald SendConfigureAck(packet);
957de2f76e1SWaldemar Kornewald break;
958de2f76e1SWaldemar Kornewald
959de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
960e3724c38Smshlyn TRACE("%s::%s: PPP_ACK_RCVD_STATE\n", __FILE__, __func__);
961de2f76e1SWaldemar Kornewald NewState(PPP_OPENED_STATE);
962de2f76e1SWaldemar Kornewald SendConfigureAck(packet);
963de2f76e1SWaldemar Kornewald ThisLayerUp();
964de2f76e1SWaldemar Kornewald break;
965de2f76e1SWaldemar Kornewald
966de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
967e3724c38Smshlyn TRACE("%s::%s: PPP_OPENED_STATE\n", __FILE__, __func__);
968de2f76e1SWaldemar Kornewald NewState(PPP_ACK_SENT_STATE);
969de2f76e1SWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
970de2f76e1SWaldemar Kornewald // indicates to handlers that we are reconfiguring
971de2f76e1SWaldemar Kornewald ThisLayerDown();
972de2f76e1SWaldemar Kornewald SendConfigureRequest();
973de2f76e1SWaldemar Kornewald SendConfigureAck(packet);
974de2f76e1SWaldemar Kornewald break;
975de2f76e1SWaldemar Kornewald
976de2f76e1SWaldemar Kornewald default:
977e3724c38Smshlyn TRACE("free peer's ppp request packet\n");
978e3724c38Smshlyn gBufferModule->free(packet);
979de2f76e1SWaldemar Kornewald }
980de2f76e1SWaldemar Kornewald }
981de2f76e1SWaldemar Kornewald
982de2f76e1SWaldemar Kornewald
983de2f76e1SWaldemar Kornewald // receive configure request (unacceptable request)
984de2f76e1SWaldemar Kornewald void
RCRBadEvent(net_buffer * nak,net_buffer * reject)985e3724c38Smshlyn KPPPStateMachine::RCRBadEvent(net_buffer *nak, net_buffer *reject)
986de2f76e1SWaldemar Kornewald {
98784b580c4SWaldemar Kornewald TRACE("KPPPSM: RCRBadEvent() state=%d phase=%d\n", State(), Phase());
9884e0ad752SWaldemar Kornewald
989e3724c38Smshlyn uint16 lenNak = 0;
990e3724c38Smshlyn uint16 lenReject = 0;
991e3724c38Smshlyn
992de2f76e1SWaldemar Kornewald switch (State()) {
993de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
994de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
995de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RCR_BAD_EVENT);
996de2f76e1SWaldemar Kornewald break;
997de2f76e1SWaldemar Kornewald
998de2f76e1SWaldemar Kornewald case PPP_CLOSED_STATE:
999de2f76e1SWaldemar Kornewald SendTerminateAck();
1000de2f76e1SWaldemar Kornewald break;
1001de2f76e1SWaldemar Kornewald
1002de2f76e1SWaldemar Kornewald case PPP_STOPPED_STATE:
1003de2f76e1SWaldemar Kornewald // irc,scr,scn/6
1004de2f76e1SWaldemar Kornewald // XXX: should we do nothing and wait for DownEvent()?
1005de2f76e1SWaldemar Kornewald break;
1006de2f76e1SWaldemar Kornewald
1007de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
1008de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1009de2f76e1SWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
1010de2f76e1SWaldemar Kornewald // indicates to handlers that we are reconfiguring
1011de2f76e1SWaldemar Kornewald ThisLayerDown();
1012de2f76e1SWaldemar Kornewald SendConfigureRequest();
1013de2f76e1SWaldemar Kornewald
1014de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
1015de2f76e1SWaldemar Kornewald if (State() == PPP_ACK_SENT_STATE)
1016de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1017de2f76e1SWaldemar Kornewald // OPENED_STATE might have set this already
1018de2f76e1SWaldemar Kornewald
1019de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
1020de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
1021e3724c38Smshlyn if (nak) {
1022e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> nakBufferHeader(nak);
1023e3724c38Smshlyn if (nakBufferHeader.Status() < B_OK)
1024e3724c38Smshlyn break;
1025e3724c38Smshlyn ppp_lcp_packet &nakHeader = nakBufferHeader.Data();
1026e3724c38Smshlyn lenNak = nakHeader.length;
1027e3724c38Smshlyn }
1028e3724c38Smshlyn
1029e3724c38Smshlyn if (reject) {
1030e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> rejectBufferHeader(reject);
1031e3724c38Smshlyn if (rejectBufferHeader.Status() < B_OK)
1032e3724c38Smshlyn break;
1033e3724c38Smshlyn ppp_lcp_packet &rejectHeader = rejectBufferHeader.Data();
1034e3724c38Smshlyn lenReject = rejectHeader.length;
1035e3724c38Smshlyn }
1036e3724c38Smshlyn
1037e3724c38Smshlyn if (nak && lenNak > 3)
1038de2f76e1SWaldemar Kornewald SendConfigureNak(nak);
1039e3724c38Smshlyn else if (reject && lenReject > 3)
1040de2f76e1SWaldemar Kornewald SendConfigureNak(reject);
1041de2f76e1SWaldemar Kornewald return;
1042de2f76e1SWaldemar Kornewald // prevents the nak/reject from being m_freem()'d
1043de2f76e1SWaldemar Kornewald
1044de2f76e1SWaldemar Kornewald default:
1045de2f76e1SWaldemar Kornewald ;
1046de2f76e1SWaldemar Kornewald }
1047de2f76e1SWaldemar Kornewald
1048de2f76e1SWaldemar Kornewald if (nak)
1049e3724c38Smshlyn gBufferModule->free(nak);
1050de2f76e1SWaldemar Kornewald if (reject)
1051e3724c38Smshlyn gBufferModule->free(reject);
1052de2f76e1SWaldemar Kornewald }
1053de2f76e1SWaldemar Kornewald
1054de2f76e1SWaldemar Kornewald
1055de2f76e1SWaldemar Kornewald // receive configure ack
1056de2f76e1SWaldemar Kornewald void
RCAEvent(net_buffer * packet)1057e3724c38Smshlyn KPPPStateMachine::RCAEvent(net_buffer *packet)
1058de2f76e1SWaldemar Kornewald {
105984b580c4SWaldemar Kornewald TRACE("KPPPSM: RCAEvent() state=%d phase=%d\n", State(), Phase());
10604e0ad752SWaldemar Kornewald
1061e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1062e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1063e3724c38Smshlyn return;
1064e3724c38Smshlyn ppp_lcp_packet &header = bufferHeader.Data();
1065e3724c38Smshlyn
1066e3724c38Smshlyn if (fRequestID != header.id) {
1067de2f76e1SWaldemar Kornewald // this packet is not a reply to our request
1068de2f76e1SWaldemar Kornewald
1069de2f76e1SWaldemar Kornewald // TODO:
1070de2f76e1SWaldemar Kornewald // log this event
1071e3724c38Smshlyn gBufferModule->free(packet);
1072de2f76e1SWaldemar Kornewald return;
1073de2f76e1SWaldemar Kornewald }
1074de2f76e1SWaldemar Kornewald
1075de2f76e1SWaldemar Kornewald // let the option handlers parse this ack
1076f9ad2df8SWaldemar Kornewald KPPPConfigurePacket ack(packet);
1077f9ad2df8SWaldemar Kornewald KPPPOptionHandler *optionHandler;
1078de2f76e1SWaldemar Kornewald for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
107992a8026eSWaldemar Kornewald optionHandler = LCP().OptionHandlerAt(index);
108092a8026eSWaldemar Kornewald if (optionHandler->ParseAck(ack) != B_OK) {
1081e3724c38Smshlyn gBufferModule->free(packet);
1082de2f76e1SWaldemar Kornewald CloseEvent();
1083de2f76e1SWaldemar Kornewald return;
1084de2f76e1SWaldemar Kornewald }
1085de2f76e1SWaldemar Kornewald }
1086de2f76e1SWaldemar Kornewald
1087de2f76e1SWaldemar Kornewald switch (State()) {
1088de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
1089de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
1090de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RCA_EVENT);
1091de2f76e1SWaldemar Kornewald break;
1092de2f76e1SWaldemar Kornewald
1093de2f76e1SWaldemar Kornewald case PPP_CLOSED_STATE:
1094de2f76e1SWaldemar Kornewald case PPP_STOPPED_STATE:
1095de2f76e1SWaldemar Kornewald SendTerminateAck();
1096de2f76e1SWaldemar Kornewald break;
1097de2f76e1SWaldemar Kornewald
1098de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
1099de2f76e1SWaldemar Kornewald NewState(PPP_ACK_RCVD_STATE);
1100de2f76e1SWaldemar Kornewald InitializeRestartCount();
1101de2f76e1SWaldemar Kornewald break;
1102de2f76e1SWaldemar Kornewald
1103de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
1104de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1105de2f76e1SWaldemar Kornewald SendConfigureRequest();
1106de2f76e1SWaldemar Kornewald break;
1107de2f76e1SWaldemar Kornewald
1108de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
1109de2f76e1SWaldemar Kornewald NewState(PPP_OPENED_STATE);
1110de2f76e1SWaldemar Kornewald InitializeRestartCount();
1111de2f76e1SWaldemar Kornewald ThisLayerUp();
1112de2f76e1SWaldemar Kornewald break;
1113de2f76e1SWaldemar Kornewald
1114de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
1115de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1116de2f76e1SWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
1117de2f76e1SWaldemar Kornewald // indicates to handlers that we are reconfiguring
1118de2f76e1SWaldemar Kornewald ThisLayerDown();
1119de2f76e1SWaldemar Kornewald SendConfigureRequest();
1120de2f76e1SWaldemar Kornewald break;
1121de2f76e1SWaldemar Kornewald
1122de2f76e1SWaldemar Kornewald default:
1123de2f76e1SWaldemar Kornewald ;
1124de2f76e1SWaldemar Kornewald }
1125de2f76e1SWaldemar Kornewald
1126e3724c38Smshlyn gBufferModule->free(packet);
1127de2f76e1SWaldemar Kornewald }
1128de2f76e1SWaldemar Kornewald
1129de2f76e1SWaldemar Kornewald
1130de2f76e1SWaldemar Kornewald // receive configure nak/reject
1131de2f76e1SWaldemar Kornewald void
RCNEvent(net_buffer * packet)1132e3724c38Smshlyn KPPPStateMachine::RCNEvent(net_buffer *packet)
1133de2f76e1SWaldemar Kornewald {
113484b580c4SWaldemar Kornewald TRACE("KPPPSM: RCNEvent() state=%d phase=%d\n", State(), Phase());
11354e0ad752SWaldemar Kornewald
1136e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1137e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1138e3724c38Smshlyn return;
1139e3724c38Smshlyn ppp_lcp_packet &header = bufferHeader.Data();
1140e3724c38Smshlyn
1141e3724c38Smshlyn if (fRequestID != header.id) {
1142de2f76e1SWaldemar Kornewald // this packet is not a reply to our request
1143de2f76e1SWaldemar Kornewald
1144de2f76e1SWaldemar Kornewald // TODO:
1145de2f76e1SWaldemar Kornewald // log this event
1146e3724c38Smshlyn gBufferModule->free(packet);
1147de2f76e1SWaldemar Kornewald return;
1148de2f76e1SWaldemar Kornewald }
1149de2f76e1SWaldemar Kornewald
1150de2f76e1SWaldemar Kornewald // let the option handlers parse this nak/reject
1151f9ad2df8SWaldemar Kornewald KPPPConfigurePacket nak_reject(packet);
1152f9ad2df8SWaldemar Kornewald KPPPOptionHandler *optionHandler;
1153de2f76e1SWaldemar Kornewald for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
115492a8026eSWaldemar Kornewald optionHandler = LCP().OptionHandlerAt(index);
1155de2f76e1SWaldemar Kornewald
1156de2f76e1SWaldemar Kornewald if (nak_reject.Code() == PPP_CONFIGURE_NAK) {
115792a8026eSWaldemar Kornewald if (optionHandler->ParseNak(nak_reject) != B_OK) {
1158e3724c38Smshlyn gBufferModule->free(packet);
1159de2f76e1SWaldemar Kornewald CloseEvent();
1160de2f76e1SWaldemar Kornewald return;
1161de2f76e1SWaldemar Kornewald }
1162de2f76e1SWaldemar Kornewald } else if (nak_reject.Code() == PPP_CONFIGURE_REJECT) {
116392a8026eSWaldemar Kornewald if (optionHandler->ParseReject(nak_reject) != B_OK) {
1164e3724c38Smshlyn gBufferModule->free(packet);
1165de2f76e1SWaldemar Kornewald CloseEvent();
1166de2f76e1SWaldemar Kornewald return;
1167de2f76e1SWaldemar Kornewald }
1168de2f76e1SWaldemar Kornewald }
1169de2f76e1SWaldemar Kornewald }
1170de2f76e1SWaldemar Kornewald
1171de2f76e1SWaldemar Kornewald switch (State()) {
1172de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
1173de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
1174de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RCN_EVENT);
1175de2f76e1SWaldemar Kornewald break;
1176de2f76e1SWaldemar Kornewald
1177de2f76e1SWaldemar Kornewald case PPP_CLOSED_STATE:
1178de2f76e1SWaldemar Kornewald case PPP_STOPPED_STATE:
1179de2f76e1SWaldemar Kornewald SendTerminateAck();
1180de2f76e1SWaldemar Kornewald break;
1181de2f76e1SWaldemar Kornewald
1182de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
1183de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
1184de2f76e1SWaldemar Kornewald InitializeRestartCount();
1185de2f76e1SWaldemar Kornewald
1186de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
1187de2f76e1SWaldemar Kornewald if (State() == PPP_ACK_RCVD_STATE)
1188de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1189de2f76e1SWaldemar Kornewald SendConfigureRequest();
1190de2f76e1SWaldemar Kornewald break;
1191de2f76e1SWaldemar Kornewald
1192de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
1193de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1194de2f76e1SWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
1195de2f76e1SWaldemar Kornewald // indicates to handlers that we are reconfiguring
1196de2f76e1SWaldemar Kornewald ThisLayerDown();
1197de2f76e1SWaldemar Kornewald SendConfigureRequest();
1198de2f76e1SWaldemar Kornewald break;
1199de2f76e1SWaldemar Kornewald
1200de2f76e1SWaldemar Kornewald default:
1201de2f76e1SWaldemar Kornewald ;
1202de2f76e1SWaldemar Kornewald }
1203de2f76e1SWaldemar Kornewald
1204e3724c38Smshlyn gBufferModule->free(packet);
1205de2f76e1SWaldemar Kornewald }
1206de2f76e1SWaldemar Kornewald
1207de2f76e1SWaldemar Kornewald
1208de2f76e1SWaldemar Kornewald // receive terminate request
1209de2f76e1SWaldemar Kornewald void
RTREvent(net_buffer * packet)1210e3724c38Smshlyn KPPPStateMachine::RTREvent(net_buffer *packet)
1211de2f76e1SWaldemar Kornewald {
121284b580c4SWaldemar Kornewald TRACE("KPPPSM: RTREvent() state=%d phase=%d\n", State(), Phase());
12134e0ad752SWaldemar Kornewald
1214e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1215e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1216e3724c38Smshlyn return;
1217e3724c38Smshlyn ppp_lcp_packet &header = bufferHeader.Data();
1218e3724c38Smshlyn
1219de2f76e1SWaldemar Kornewald // we should not use the same ID as the peer
1220e3724c38Smshlyn if (fID == header.id)
1221de2f76e1SWaldemar Kornewald fID -= 128;
1222de2f76e1SWaldemar Kornewald
1223de2f76e1SWaldemar Kornewald fLocalAuthenticationStatus = PPP_NOT_AUTHENTICATED;
1224de2f76e1SWaldemar Kornewald fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED;
1225de2f76e1SWaldemar Kornewald
1226de2f76e1SWaldemar Kornewald switch (State()) {
1227de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
1228de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
1229de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RTR_EVENT);
1230e3724c38Smshlyn gBufferModule->free(packet);
1231de2f76e1SWaldemar Kornewald break;
1232de2f76e1SWaldemar Kornewald
1233de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
1234de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
1235de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1236de2f76e1SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
1237de2f76e1SWaldemar Kornewald // indicates to handlers that we are terminating
1238de2f76e1SWaldemar Kornewald SendTerminateAck(packet);
1239de2f76e1SWaldemar Kornewald break;
1240de2f76e1SWaldemar Kornewald
1241de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
1242de2f76e1SWaldemar Kornewald NewState(PPP_STOPPING_STATE);
1243de2f76e1SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
1244de2f76e1SWaldemar Kornewald // indicates to handlers that we are terminating
1245de2f76e1SWaldemar Kornewald ZeroRestartCount();
1246de2f76e1SWaldemar Kornewald ThisLayerDown();
1247de2f76e1SWaldemar Kornewald SendTerminateAck(packet);
1248de2f76e1SWaldemar Kornewald break;
1249de2f76e1SWaldemar Kornewald
1250de2f76e1SWaldemar Kornewald default:
1251de2f76e1SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
1252de2f76e1SWaldemar Kornewald // indicates to handlers that we are terminating
1253de2f76e1SWaldemar Kornewald SendTerminateAck(packet);
1254de2f76e1SWaldemar Kornewald }
1255de2f76e1SWaldemar Kornewald }
1256de2f76e1SWaldemar Kornewald
1257de2f76e1SWaldemar Kornewald
1258de2f76e1SWaldemar Kornewald // receive terminate ack
1259de2f76e1SWaldemar Kornewald void
RTAEvent(net_buffer * packet)1260e3724c38Smshlyn KPPPStateMachine::RTAEvent(net_buffer *packet)
1261de2f76e1SWaldemar Kornewald {
126284b580c4SWaldemar Kornewald TRACE("KPPPSM: RTAEvent() state=%d phase=%d\n", State(), Phase());
12634e0ad752SWaldemar Kornewald
1264e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1265e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1266e3724c38Smshlyn return;
1267e3724c38Smshlyn ppp_lcp_packet &header = bufferHeader.Data();
1268e3724c38Smshlyn
1269e3724c38Smshlyn if (fTerminateID != header.id) {
1270de2f76e1SWaldemar Kornewald // this packet is not a reply to our request
1271de2f76e1SWaldemar Kornewald
1272de2f76e1SWaldemar Kornewald // TODO:
1273de2f76e1SWaldemar Kornewald // log this event
1274e3724c38Smshlyn gBufferModule->free(packet);
1275de2f76e1SWaldemar Kornewald return;
1276de2f76e1SWaldemar Kornewald }
1277de2f76e1SWaldemar Kornewald
1278de2f76e1SWaldemar Kornewald switch (State()) {
1279de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
1280de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
1281de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RTA_EVENT);
1282de2f76e1SWaldemar Kornewald break;
1283de2f76e1SWaldemar Kornewald
1284de2f76e1SWaldemar Kornewald case PPP_CLOSING_STATE:
1285de2f76e1SWaldemar Kornewald NewState(PPP_CLOSED_STATE);
1286de2f76e1SWaldemar Kornewald ThisLayerFinished();
1287de2f76e1SWaldemar Kornewald break;
1288de2f76e1SWaldemar Kornewald
1289de2f76e1SWaldemar Kornewald case PPP_STOPPING_STATE:
1290de2f76e1SWaldemar Kornewald NewState(PPP_STOPPED_STATE);
1291de2f76e1SWaldemar Kornewald ThisLayerFinished();
1292de2f76e1SWaldemar Kornewald break;
1293de2f76e1SWaldemar Kornewald
1294de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
1295de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1296de2f76e1SWaldemar Kornewald break;
1297de2f76e1SWaldemar Kornewald
1298de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
1299de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1300de2f76e1SWaldemar Kornewald NewPhase(PPP_ESTABLISHMENT_PHASE);
1301de2f76e1SWaldemar Kornewald // indicates to handlers that we are reconfiguring
1302de2f76e1SWaldemar Kornewald ThisLayerDown();
1303de2f76e1SWaldemar Kornewald SendConfigureRequest();
1304de2f76e1SWaldemar Kornewald break;
1305de2f76e1SWaldemar Kornewald
1306de2f76e1SWaldemar Kornewald default:
1307de2f76e1SWaldemar Kornewald ;
1308de2f76e1SWaldemar Kornewald }
1309de2f76e1SWaldemar Kornewald
1310e3724c38Smshlyn gBufferModule->free(packet);
1311de2f76e1SWaldemar Kornewald }
1312de2f76e1SWaldemar Kornewald
1313de2f76e1SWaldemar Kornewald
1314de2f76e1SWaldemar Kornewald // receive unknown code
1315de2f76e1SWaldemar Kornewald void
RUCEvent(net_buffer * packet,uint16 protocolNumber,uint8 code)1316e3724c38Smshlyn KPPPStateMachine::RUCEvent(net_buffer *packet, uint16 protocolNumber,
1317758b1d0eSIngo Weinhold uint8 code)
1318de2f76e1SWaldemar Kornewald {
131984b580c4SWaldemar Kornewald TRACE("KPPPSM: RUCEvent() state=%d phase=%d\n", State(), Phase());
13204e0ad752SWaldemar Kornewald
1321de2f76e1SWaldemar Kornewald switch (State()) {
1322de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
1323de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
1324de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RUC_EVENT);
1325e3724c38Smshlyn gBufferModule->free(packet);
1326de2f76e1SWaldemar Kornewald break;
1327de2f76e1SWaldemar Kornewald
1328de2f76e1SWaldemar Kornewald default:
132992a8026eSWaldemar Kornewald SendCodeReject(packet, protocolNumber, code);
1330de2f76e1SWaldemar Kornewald }
1331de2f76e1SWaldemar Kornewald }
1332de2f76e1SWaldemar Kornewald
1333de2f76e1SWaldemar Kornewald
1334de2f76e1SWaldemar Kornewald // receive code/protocol reject (acceptable such as IPX reject)
1335de2f76e1SWaldemar Kornewald void
RXJGoodEvent(net_buffer * packet)1336e3724c38Smshlyn KPPPStateMachine::RXJGoodEvent(net_buffer *packet)
1337de2f76e1SWaldemar Kornewald {
133884b580c4SWaldemar Kornewald TRACE("KPPPSM: RXJGoodEvent() state=%d phase=%d\n", State(), Phase());
13394e0ad752SWaldemar Kornewald
1340de2f76e1SWaldemar Kornewald // This method does not m_freem(packet) because the acceptable rejects are
1341de2f76e1SWaldemar Kornewald // also passed to the parent. RXJEvent() will m_freem(packet) when needed.
1342de2f76e1SWaldemar Kornewald
1343de2f76e1SWaldemar Kornewald switch (State()) {
1344de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
1345de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
1346de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RXJ_GOOD_EVENT);
1347de2f76e1SWaldemar Kornewald break;
1348de2f76e1SWaldemar Kornewald
1349de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
1350de2f76e1SWaldemar Kornewald NewState(PPP_REQ_SENT_STATE);
1351de2f76e1SWaldemar Kornewald break;
1352de2f76e1SWaldemar Kornewald
1353de2f76e1SWaldemar Kornewald default:
1354de2f76e1SWaldemar Kornewald ;
1355de2f76e1SWaldemar Kornewald }
1356de2f76e1SWaldemar Kornewald }
1357de2f76e1SWaldemar Kornewald
1358de2f76e1SWaldemar Kornewald
1359de2f76e1SWaldemar Kornewald // receive code/protocol reject (catastrophic such as LCP reject)
1360de2f76e1SWaldemar Kornewald void
RXJBadEvent(net_buffer * packet)1361e3724c38Smshlyn KPPPStateMachine::RXJBadEvent(net_buffer *packet)
1362de2f76e1SWaldemar Kornewald {
136384b580c4SWaldemar Kornewald TRACE("KPPPSM: RXJBadEvent() state=%d phase=%d\n", State(), Phase());
13644e0ad752SWaldemar Kornewald
1365de2f76e1SWaldemar Kornewald switch (State()) {
1366de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
1367de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
1368de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RXJ_BAD_EVENT);
1369de2f76e1SWaldemar Kornewald break;
1370de2f76e1SWaldemar Kornewald
1371de2f76e1SWaldemar Kornewald case PPP_CLOSING_STATE:
1372de2f76e1SWaldemar Kornewald NewState(PPP_CLOSED_STATE);
1373de2f76e1SWaldemar Kornewald
1374de2f76e1SWaldemar Kornewald case PPP_CLOSED_STATE:
1375de2f76e1SWaldemar Kornewald ThisLayerFinished();
1376de2f76e1SWaldemar Kornewald break;
1377de2f76e1SWaldemar Kornewald
1378de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
1379de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
1380de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
1381de2f76e1SWaldemar Kornewald NewState(PPP_STOPPED_STATE);
1382de2f76e1SWaldemar Kornewald
1383de2f76e1SWaldemar Kornewald case PPP_STOPPING_STATE:
1384de2f76e1SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
1385de2f76e1SWaldemar Kornewald
1386de2f76e1SWaldemar Kornewald case PPP_STOPPED_STATE:
1387de2f76e1SWaldemar Kornewald ThisLayerFinished();
1388de2f76e1SWaldemar Kornewald break;
1389de2f76e1SWaldemar Kornewald
1390de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
1391de2f76e1SWaldemar Kornewald NewState(PPP_STOPPING_STATE);
1392de2f76e1SWaldemar Kornewald NewPhase(PPP_TERMINATION_PHASE);
1393de2f76e1SWaldemar Kornewald // indicates to handlers that we are terminating
1394de2f76e1SWaldemar Kornewald InitializeRestartCount();
1395de2f76e1SWaldemar Kornewald ThisLayerDown();
1396de2f76e1SWaldemar Kornewald SendTerminateRequest();
1397de2f76e1SWaldemar Kornewald break;
1398de2f76e1SWaldemar Kornewald }
1399de2f76e1SWaldemar Kornewald
1400e3724c38Smshlyn gBufferModule->free(packet);
1401de2f76e1SWaldemar Kornewald }
1402de2f76e1SWaldemar Kornewald
1403de2f76e1SWaldemar Kornewald
1404de2f76e1SWaldemar Kornewald // receive echo request/reply, discard request
1405de2f76e1SWaldemar Kornewald void
RXREvent(net_buffer * packet)1406e3724c38Smshlyn KPPPStateMachine::RXREvent(net_buffer *packet)
1407de2f76e1SWaldemar Kornewald {
140884b580c4SWaldemar Kornewald TRACE("KPPPSM: RXREvent() state=%d phase=%d\n", State(), Phase());
14094e0ad752SWaldemar Kornewald
1410e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1411e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1412e3724c38Smshlyn return;
1413e3724c38Smshlyn ppp_lcp_packet &echo = bufferHeader.Data();
1414de2f76e1SWaldemar Kornewald
1415e3724c38Smshlyn if (echo.code == PPP_ECHO_REPLY && echo.id != fEchoID) {
1416de2f76e1SWaldemar Kornewald // TODO:
1417de2f76e1SWaldemar Kornewald // log that we got a reply, but no request was sent
1418de2f76e1SWaldemar Kornewald }
1419de2f76e1SWaldemar Kornewald
1420de2f76e1SWaldemar Kornewald switch (State()) {
1421de2f76e1SWaldemar Kornewald case PPP_INITIAL_STATE:
1422de2f76e1SWaldemar Kornewald case PPP_STARTING_STATE:
1423de2f76e1SWaldemar Kornewald IllegalEvent(PPP_RXR_EVENT);
1424de2f76e1SWaldemar Kornewald break;
1425de2f76e1SWaldemar Kornewald
1426de2f76e1SWaldemar Kornewald case PPP_OPENED_STATE:
1427e3724c38Smshlyn if (echo.code == PPP_ECHO_REQUEST)
1428de2f76e1SWaldemar Kornewald SendEchoReply(packet);
1429de2f76e1SWaldemar Kornewald return;
1430de2f76e1SWaldemar Kornewald // this prevents the packet from being freed
1431de2f76e1SWaldemar Kornewald
1432de2f76e1SWaldemar Kornewald default:
1433de2f76e1SWaldemar Kornewald ;
1434de2f76e1SWaldemar Kornewald }
1435de2f76e1SWaldemar Kornewald
1436e3724c38Smshlyn gBufferModule->free(packet);
1437de2f76e1SWaldemar Kornewald }
1438de2f76e1SWaldemar Kornewald
1439de2f76e1SWaldemar Kornewald
1440de2f76e1SWaldemar Kornewald // general events (for Good/Bad events)
1441de2f76e1SWaldemar Kornewald void
TimerEvent()1442f9ad2df8SWaldemar Kornewald KPPPStateMachine::TimerEvent()
1443de2f76e1SWaldemar Kornewald {
14444e0ad752SWaldemar Kornewald #if DEBUG
14454e0ad752SWaldemar Kornewald if (fNextTimeout != 0)
144684b580c4SWaldemar Kornewald TRACE("KPPPSM: TimerEvent()\n");
14474e0ad752SWaldemar Kornewald #endif
14484e0ad752SWaldemar Kornewald
14492f13f213SWaldemar Kornewald if (fNextTimeout == 0 || fNextTimeout > system_time())
1450de2f76e1SWaldemar Kornewald return;
14512f13f213SWaldemar Kornewald
1452de2f76e1SWaldemar Kornewald fNextTimeout = 0;
1453de2f76e1SWaldemar Kornewald
1454de2f76e1SWaldemar Kornewald switch (State()) {
1455de2f76e1SWaldemar Kornewald case PPP_CLOSING_STATE:
1456de2f76e1SWaldemar Kornewald case PPP_STOPPING_STATE:
1457de2f76e1SWaldemar Kornewald if (fTerminateCounter <= 0)
1458de2f76e1SWaldemar Kornewald TOBadEvent();
1459de2f76e1SWaldemar Kornewald else
1460de2f76e1SWaldemar Kornewald TOGoodEvent();
1461de2f76e1SWaldemar Kornewald break;
1462de2f76e1SWaldemar Kornewald
1463de2f76e1SWaldemar Kornewald case PPP_REQ_SENT_STATE:
1464de2f76e1SWaldemar Kornewald case PPP_ACK_RCVD_STATE:
1465de2f76e1SWaldemar Kornewald case PPP_ACK_SENT_STATE:
1466de2f76e1SWaldemar Kornewald if (fRequestCounter <= 0)
1467de2f76e1SWaldemar Kornewald TOBadEvent();
1468de2f76e1SWaldemar Kornewald else
1469de2f76e1SWaldemar Kornewald TOGoodEvent();
1470de2f76e1SWaldemar Kornewald break;
1471de2f76e1SWaldemar Kornewald
1472de2f76e1SWaldemar Kornewald default:
1473de2f76e1SWaldemar Kornewald ;
1474de2f76e1SWaldemar Kornewald }
1475de2f76e1SWaldemar Kornewald }
1476de2f76e1SWaldemar Kornewald
1477de2f76e1SWaldemar Kornewald
1478de2f76e1SWaldemar Kornewald // ReceiveConfigureRequest
1479e3724c38Smshlyn // Here we get a configure-request packet from LCP and ask all OptionHandlers
1480de2f76e1SWaldemar Kornewald // if its values are acceptable. From here we call our Good/Bad counterparts.
1481de2f76e1SWaldemar Kornewald void
RCREvent(net_buffer * packet)1482e3724c38Smshlyn KPPPStateMachine::RCREvent(net_buffer *packet)
1483de2f76e1SWaldemar Kornewald {
1484e3724c38Smshlyn TRACE("KPPPSM: RCREvent() state=%d phase=%d lcppacket size=%ld\n", State(), Phase(),
1485e3724c38Smshlyn packet->size);
14864e0ad752SWaldemar Kornewald
1487f9ad2df8SWaldemar Kornewald KPPPConfigurePacket request(packet);
1488f9ad2df8SWaldemar Kornewald KPPPConfigurePacket nak(PPP_CONFIGURE_NAK);
1489f9ad2df8SWaldemar Kornewald KPPPConfigurePacket reject(PPP_CONFIGURE_REJECT);
1490de2f76e1SWaldemar Kornewald
1491e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1492e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1493e3724c38Smshlyn return;
1494e3724c38Smshlyn ppp_lcp_packet &header = bufferHeader.Data();
1495e3724c38Smshlyn
1496de2f76e1SWaldemar Kornewald // we should not use the same id as the peer
1497e3724c38Smshlyn if (fID == header.id)
1498de2f76e1SWaldemar Kornewald fID -= 128;
1499e3724c38Smshlyn // or maybe we should use peer's ID plus 1 ?
1500de2f76e1SWaldemar Kornewald
1501de2f76e1SWaldemar Kornewald nak.SetID(request.ID());
1502de2f76e1SWaldemar Kornewald reject.SetID(request.ID());
1503de2f76e1SWaldemar Kornewald
1504de2f76e1SWaldemar Kornewald // each handler should add unacceptable values for each item
1505de2f76e1SWaldemar Kornewald status_t result;
1506de2f76e1SWaldemar Kornewald // the return value of ParseRequest()
1507f9ad2df8SWaldemar Kornewald KPPPOptionHandler *optionHandler;
1508de2f76e1SWaldemar Kornewald for (int32 index = 0; index < request.CountItems(); index++) {
150992a8026eSWaldemar Kornewald optionHandler = LCP().OptionHandlerFor(request.ItemAt(index)->type);
1510de2f76e1SWaldemar Kornewald
151192a8026eSWaldemar Kornewald if (!optionHandler || !optionHandler->IsEnabled()) {
1512e3724c38Smshlyn TRACE("KPPPSM::RCREvent():unknown type:%d\n", request.ItemAt(index)->type);
1513e3724c38Smshlyn if (request.ItemAt(index)->type == 0x5)
1514e3724c38Smshlyn {
1515e3724c38Smshlyn // type 0x5 is Magic Number, Need no processing.
1516e3724c38Smshlyn TRACE("Peer Magic Number:%02x %02x %02x %02x\n",
1517e3724c38Smshlyn (request.ItemAt(index)->data)[0],
1518e3724c38Smshlyn (request.ItemAt(index)->data)[1],
1519e3724c38Smshlyn (request.ItemAt(index)->data)[2],
1520e3724c38Smshlyn (request.ItemAt(index)->data)[3]);
1521e3724c38Smshlyn continue;
1522e3724c38Smshlyn } else {
1523de2f76e1SWaldemar Kornewald // unhandled items should be added to the reject
1524e3724c38Smshlyn TRACE("why come here %ld\n", index);
1525de2f76e1SWaldemar Kornewald reject.AddItem(request.ItemAt(index));
1526de2f76e1SWaldemar Kornewald continue;
1527de2f76e1SWaldemar Kornewald }
1528e3724c38Smshlyn }
1529de2f76e1SWaldemar Kornewald
153084b580c4SWaldemar Kornewald TRACE("KPPPSM::RCREvent(): OH=%s\n",
1531abf44d1aSWaldemar Kornewald optionHandler->Name() ? optionHandler->Name() : "Unknown");
153292a8026eSWaldemar Kornewald result = optionHandler->ParseRequest(request, index, nak, reject);
1533de2f76e1SWaldemar Kornewald
1534de2f76e1SWaldemar Kornewald if (result == PPP_UNHANDLED) {
1535de2f76e1SWaldemar Kornewald // unhandled items should be added to the reject
1536e3724c38Smshlyn TRACE("PPP_UNHANDLED %ld\n", index);
1537de2f76e1SWaldemar Kornewald reject.AddItem(request.ItemAt(index));
1538de2f76e1SWaldemar Kornewald continue;
1539de2f76e1SWaldemar Kornewald } else if (result != B_OK) {
1540de2f76e1SWaldemar Kornewald // the request contains a value that has been sent more than
1541de2f76e1SWaldemar Kornewald // once or the value is corrupted
154284b580c4SWaldemar Kornewald ERROR("KPPPSM::RCREvent(): OptionHandler returned parse error!\n");
1543e3724c38Smshlyn gBufferModule->free(packet);
1544de2f76e1SWaldemar Kornewald CloseEvent();
1545de2f76e1SWaldemar Kornewald return;
1546de2f76e1SWaldemar Kornewald }
1547de2f76e1SWaldemar Kornewald }
1548de2f76e1SWaldemar Kornewald
1549de2f76e1SWaldemar Kornewald // Additional values may be appended.
1550de2f76e1SWaldemar Kornewald // If we sent too many naks we should not append additional values.
1551de2f76e1SWaldemar Kornewald if (fNakCounter > 0) {
1552de2f76e1SWaldemar Kornewald for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
155392a8026eSWaldemar Kornewald optionHandler = LCP().OptionHandlerAt(index);
155492a8026eSWaldemar Kornewald if (optionHandler && optionHandler->IsEnabled()) {
155592a8026eSWaldemar Kornewald result = optionHandler->ParseRequest(request, request.CountItems(),
1556de2f76e1SWaldemar Kornewald nak, reject);
1557de2f76e1SWaldemar Kornewald
1558de2f76e1SWaldemar Kornewald if (result != B_OK) {
1559de2f76e1SWaldemar Kornewald // the request contains a value that has been sent more than
1560de2f76e1SWaldemar Kornewald // once or the value is corrupted
156184b580c4SWaldemar Kornewald ERROR("KPPPSM::RCREvent():OptionHandler returned append error!\n");
1562e3724c38Smshlyn gBufferModule->free(packet);
1563de2f76e1SWaldemar Kornewald CloseEvent();
1564de2f76e1SWaldemar Kornewald return;
1565de2f76e1SWaldemar Kornewald }
1566de2f76e1SWaldemar Kornewald }
1567de2f76e1SWaldemar Kornewald }
1568de2f76e1SWaldemar Kornewald }
1569de2f76e1SWaldemar Kornewald
1570abdb7d1aSWaldemar Kornewald if (reject.CountItems() > 0) {
1571e3724c38Smshlyn TRACE("%s:reject number more than 0\n", __func__);
1572e3724c38Smshlyn RCRBadEvent(NULL, reject.ToNetBuffer(Interface().MRU()));
1573e3724c38Smshlyn gBufferModule->free(packet);
1574abdb7d1aSWaldemar Kornewald } else if (nak.CountItems() > 0) {
1575e3724c38Smshlyn TRACE("%s:nak number more than 0\n", __func__);
1576e3724c38Smshlyn RCRBadEvent(nak.ToNetBuffer(Interface().MRU()), NULL);
1577e3724c38Smshlyn gBufferModule->free(packet);
1578ca43389aSWaldemar Kornewald } else
1579de2f76e1SWaldemar Kornewald RCRGoodEvent(packet);
1580de2f76e1SWaldemar Kornewald }
1581de2f76e1SWaldemar Kornewald
1582de2f76e1SWaldemar Kornewald
1583de2f76e1SWaldemar Kornewald // ReceiveCodeReject
1584de2f76e1SWaldemar Kornewald // LCP received a code/protocol-reject packet and we look if it is acceptable.
1585de2f76e1SWaldemar Kornewald // From here we call our Good/Bad counterparts.
1586de2f76e1SWaldemar Kornewald void
RXJEvent(net_buffer * packet)1587e3724c38Smshlyn KPPPStateMachine::RXJEvent(net_buffer *packet)
1588de2f76e1SWaldemar Kornewald {
158984b580c4SWaldemar Kornewald TRACE("KPPPSM: RXJEvent() state=%d phase=%d\n", State(), Phase());
15904e0ad752SWaldemar Kornewald
1591e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1592e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1593e3724c38Smshlyn return;
1594e3724c38Smshlyn ppp_lcp_packet &reject = bufferHeader.Data();
1595de2f76e1SWaldemar Kornewald
1596e3724c38Smshlyn if (reject.code == PPP_CODE_REJECT) {
1597e3724c38Smshlyn uint8 rejectedCode = reject.data[0];
1598de2f76e1SWaldemar Kornewald
1599de2f76e1SWaldemar Kornewald // test if the rejected code belongs to the minimum LCP requirements
1600de2f76e1SWaldemar Kornewald if (rejectedCode >= PPP_MIN_LCP_CODE && rejectedCode <= PPP_MAX_LCP_CODE) {
1601de2f76e1SWaldemar Kornewald if (Interface().IsMultilink() && !Interface().Parent()) {
1602de2f76e1SWaldemar Kornewald // Main interfaces do not have states between STARTING and OPENED.
1603de2f76e1SWaldemar Kornewald // An RXJBadEvent() would enter one of those states which is bad.
1604e3724c38Smshlyn gBufferModule->free(packet);
1605de2f76e1SWaldemar Kornewald CloseEvent();
1606de2f76e1SWaldemar Kornewald } else
1607de2f76e1SWaldemar Kornewald RXJBadEvent(packet);
1608de2f76e1SWaldemar Kornewald
1609de2f76e1SWaldemar Kornewald return;
1610de2f76e1SWaldemar Kornewald }
1611de2f76e1SWaldemar Kornewald
1612de2f76e1SWaldemar Kornewald // find the LCP extension and disable it
1613f9ad2df8SWaldemar Kornewald KPPPLCPExtension *lcpExtension;
1614de2f76e1SWaldemar Kornewald for (int32 index = 0; index < LCP().CountLCPExtensions(); index++) {
161592a8026eSWaldemar Kornewald lcpExtension = LCP().LCPExtensionAt(index);
1616de2f76e1SWaldemar Kornewald
161792a8026eSWaldemar Kornewald if (lcpExtension->Code() == rejectedCode)
161892a8026eSWaldemar Kornewald lcpExtension->SetEnabled(false);
1619de2f76e1SWaldemar Kornewald }
1620de2f76e1SWaldemar Kornewald
1621e3724c38Smshlyn gBufferModule->free(packet);
1622e3724c38Smshlyn } else if (reject.code == PPP_PROTOCOL_REJECT) {
1623de2f76e1SWaldemar Kornewald // disable all handlers for rejected protocol type
1624e3724c38Smshlyn uint16 rejected = *((uint16*) reject.data);
1625de2f76e1SWaldemar Kornewald // rejected protocol number
1626de2f76e1SWaldemar Kornewald
1627de2f76e1SWaldemar Kornewald if (rejected == PPP_LCP_PROTOCOL) {
1628de2f76e1SWaldemar Kornewald // LCP must not be rejected!
1629de2f76e1SWaldemar Kornewald RXJBadEvent(packet);
1630de2f76e1SWaldemar Kornewald return;
1631de2f76e1SWaldemar Kornewald }
1632de2f76e1SWaldemar Kornewald
163392a8026eSWaldemar Kornewald // disable protocols with the rejected protocol number
1634f9ad2df8SWaldemar Kornewald KPPPProtocol *protocol = Interface().FirstProtocol();
163592a8026eSWaldemar Kornewald for (; protocol; protocol = protocol->NextProtocol()) {
163692a8026eSWaldemar Kornewald if (protocol->ProtocolNumber() == rejected)
163792a8026eSWaldemar Kornewald protocol->SetEnabled(false);
1638de2f76e1SWaldemar Kornewald // disable protocol
1639de2f76e1SWaldemar Kornewald }
1640de2f76e1SWaldemar Kornewald
1641de2f76e1SWaldemar Kornewald RXJGoodEvent(packet);
1642de2f76e1SWaldemar Kornewald // this event handler does not m_freem(packet)!!!
1643de2f76e1SWaldemar Kornewald
1644de2f76e1SWaldemar Kornewald // notify parent, too
1645de2f76e1SWaldemar Kornewald if (Interface().Parent())
1646de2f76e1SWaldemar Kornewald Interface().Parent()->StateMachine().RXJEvent(packet);
1647de2f76e1SWaldemar Kornewald else
1648e3724c38Smshlyn gBufferModule->free(packet);
1649de2f76e1SWaldemar Kornewald }
1650de2f76e1SWaldemar Kornewald }
1651de2f76e1SWaldemar Kornewald
1652de2f76e1SWaldemar Kornewald
1653de2f76e1SWaldemar Kornewald // actions (all private)
1654de2f76e1SWaldemar Kornewald void
IllegalEvent(ppp_event event)1655f9ad2df8SWaldemar Kornewald KPPPStateMachine::IllegalEvent(ppp_event event)
1656de2f76e1SWaldemar Kornewald {
1657de2f76e1SWaldemar Kornewald // TODO:
1658de2f76e1SWaldemar Kornewald // update error statistics
1659e3724c38Smshlyn TRACE("KPPPSM: IllegalEvent(event=%d) state=%d phase=%d\n",
16604e0ad752SWaldemar Kornewald event, State(), Phase());
1661de2f76e1SWaldemar Kornewald }
1662de2f76e1SWaldemar Kornewald
1663de2f76e1SWaldemar Kornewald
1664de2f76e1SWaldemar Kornewald void
ThisLayerUp()1665f9ad2df8SWaldemar Kornewald KPPPStateMachine::ThisLayerUp()
1666de2f76e1SWaldemar Kornewald {
166784b580c4SWaldemar Kornewald TRACE("KPPPSM: ThisLayerUp() state=%d phase=%d\n", State(), Phase());
16684e0ad752SWaldemar Kornewald
1669de2f76e1SWaldemar Kornewald // We begin with authentication phase and wait until each phase is done.
1670de2f76e1SWaldemar Kornewald // We stop when we reach established phase.
1671de2f76e1SWaldemar Kornewald
1672de2f76e1SWaldemar Kornewald // Do not forget to check if we are going down.
1673de2f76e1SWaldemar Kornewald if (Phase() != PPP_ESTABLISHMENT_PHASE)
1674de2f76e1SWaldemar Kornewald return;
1675de2f76e1SWaldemar Kornewald
1676de2f76e1SWaldemar Kornewald NewPhase(PPP_AUTHENTICATION_PHASE);
1677de2f76e1SWaldemar Kornewald
167892a8026eSWaldemar Kornewald BringProtocolsUp();
1679de2f76e1SWaldemar Kornewald }
1680de2f76e1SWaldemar Kornewald
1681de2f76e1SWaldemar Kornewald
1682de2f76e1SWaldemar Kornewald void
ThisLayerDown()1683f9ad2df8SWaldemar Kornewald KPPPStateMachine::ThisLayerDown()
1684de2f76e1SWaldemar Kornewald {
168584b580c4SWaldemar Kornewald TRACE("KPPPSM: ThisLayerDown() state=%d phase=%d\n", State(), Phase());
16864e0ad752SWaldemar Kornewald
1687f9ad2df8SWaldemar Kornewald // KPPPProtocol::Down() should block if needed.
1688de2f76e1SWaldemar Kornewald DownProtocols();
1689de2f76e1SWaldemar Kornewald }
1690de2f76e1SWaldemar Kornewald
1691de2f76e1SWaldemar Kornewald
1692de2f76e1SWaldemar Kornewald void
ThisLayerStarted()1693f9ad2df8SWaldemar Kornewald KPPPStateMachine::ThisLayerStarted()
1694de2f76e1SWaldemar Kornewald {
169584b580c4SWaldemar Kornewald TRACE("KPPPSM: ThisLayerStarted() state=%d phase=%d\n", State(), Phase());
16964e0ad752SWaldemar Kornewald
1697e7452421SWaldemar Kornewald if (Interface().Device() && !Interface().Device()->Up())
1698e7452421SWaldemar Kornewald Interface().Device()->UpFailedEvent();
1699de2f76e1SWaldemar Kornewald }
1700de2f76e1SWaldemar Kornewald
1701de2f76e1SWaldemar Kornewald
1702de2f76e1SWaldemar Kornewald void
ThisLayerFinished()1703f9ad2df8SWaldemar Kornewald KPPPStateMachine::ThisLayerFinished()
1704de2f76e1SWaldemar Kornewald {
170584b580c4SWaldemar Kornewald TRACE("KPPPSM: ThisLayerFinished() state=%d phase=%d\n", State(), Phase());
17064e0ad752SWaldemar Kornewald
1707de2f76e1SWaldemar Kornewald if (Interface().Device())
1708de2f76e1SWaldemar Kornewald Interface().Device()->Down();
1709de2f76e1SWaldemar Kornewald }
1710de2f76e1SWaldemar Kornewald
1711de2f76e1SWaldemar Kornewald
1712de2f76e1SWaldemar Kornewald void
InitializeRestartCount()1713f9ad2df8SWaldemar Kornewald KPPPStateMachine::InitializeRestartCount()
1714de2f76e1SWaldemar Kornewald {
1715de2f76e1SWaldemar Kornewald fRequestCounter = fMaxRequest;
1716de2f76e1SWaldemar Kornewald fTerminateCounter = fMaxTerminate;
1717de2f76e1SWaldemar Kornewald fNakCounter = fMaxNak;
1718de2f76e1SWaldemar Kornewald }
1719de2f76e1SWaldemar Kornewald
1720de2f76e1SWaldemar Kornewald
1721de2f76e1SWaldemar Kornewald void
ZeroRestartCount()1722f9ad2df8SWaldemar Kornewald KPPPStateMachine::ZeroRestartCount()
1723de2f76e1SWaldemar Kornewald {
1724de2f76e1SWaldemar Kornewald fRequestCounter = 0;
1725de2f76e1SWaldemar Kornewald fTerminateCounter = 0;
1726de2f76e1SWaldemar Kornewald fNakCounter = 0;
1727de2f76e1SWaldemar Kornewald }
1728de2f76e1SWaldemar Kornewald
1729de2f76e1SWaldemar Kornewald
1730de2f76e1SWaldemar Kornewald bool
SendConfigureRequest()1731f9ad2df8SWaldemar Kornewald KPPPStateMachine::SendConfigureRequest()
1732de2f76e1SWaldemar Kornewald {
173384b580c4SWaldemar Kornewald TRACE("KPPPSM: SendConfigureRequest() state=%d phase=%d\n", State(), Phase());
17344e0ad752SWaldemar Kornewald
1735de2f76e1SWaldemar Kornewald --fRequestCounter;
17366ff76cdaSWaldemar Kornewald fNextTimeout = system_time() + kPPPStateMachineTimeout;
1737de2f76e1SWaldemar Kornewald
1738f9ad2df8SWaldemar Kornewald KPPPConfigurePacket request(PPP_CONFIGURE_REQUEST);
1739de2f76e1SWaldemar Kornewald request.SetID(NextID());
1740de2f76e1SWaldemar Kornewald fRequestID = request.ID();
1741de2f76e1SWaldemar Kornewald
1742de2f76e1SWaldemar Kornewald for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
1743de2f76e1SWaldemar Kornewald // add all items
1744de2f76e1SWaldemar Kornewald if (LCP().OptionHandlerAt(index)->AddToRequest(request) != B_OK) {
1745de2f76e1SWaldemar Kornewald CloseEvent();
1746de2f76e1SWaldemar Kornewald return false;
1747de2f76e1SWaldemar Kornewald }
1748de2f76e1SWaldemar Kornewald }
1749de2f76e1SWaldemar Kornewald
1750e3724c38Smshlyn return LCP().Send(request.ToNetBuffer(Interface().MRU())) == B_OK;
1751de2f76e1SWaldemar Kornewald }
1752de2f76e1SWaldemar Kornewald
1753de2f76e1SWaldemar Kornewald
1754de2f76e1SWaldemar Kornewald bool
SendConfigureAck(net_buffer * packet)1755e3724c38Smshlyn KPPPStateMachine::SendConfigureAck(net_buffer *packet)
1756de2f76e1SWaldemar Kornewald {
175784b580c4SWaldemar Kornewald TRACE("KPPPSM: SendConfigureAck() state=%d phase=%d\n", State(), Phase());
17584e0ad752SWaldemar Kornewald
1759de2f76e1SWaldemar Kornewald if (!packet)
1760de2f76e1SWaldemar Kornewald return false;
1761de2f76e1SWaldemar Kornewald
1762e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1763e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1764e3724c38Smshlyn return false;
1765e3724c38Smshlyn ppp_lcp_packet &header = bufferHeader.Data();
1766e3724c38Smshlyn
1767e3724c38Smshlyn header.code = PPP_CONFIGURE_ACK;
1768e3724c38Smshlyn bufferHeader.Sync();
1769e3724c38Smshlyn
1770f9ad2df8SWaldemar Kornewald KPPPConfigurePacket ack(packet);
1771de2f76e1SWaldemar Kornewald
1772de2f76e1SWaldemar Kornewald // notify all option handlers that we are sending an ack for each value
1773de2f76e1SWaldemar Kornewald for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
1774de2f76e1SWaldemar Kornewald if (LCP().OptionHandlerAt(index)->SendingAck(ack) != B_OK) {
1775e3724c38Smshlyn TRACE("%s::%s: SendingAck %ld fail\n", __FILE__, __func__, index);
1776e3724c38Smshlyn gBufferModule->free(packet);
1777de2f76e1SWaldemar Kornewald CloseEvent();
1778de2f76e1SWaldemar Kornewald return false;
1779de2f76e1SWaldemar Kornewald }
1780de2f76e1SWaldemar Kornewald }
1781de2f76e1SWaldemar Kornewald
1782e3724c38Smshlyn TRACE("%s::%s: LCP().Send\n", __FILE__, __func__);
1783de2f76e1SWaldemar Kornewald return LCP().Send(packet) == B_OK;
1784de2f76e1SWaldemar Kornewald }
1785de2f76e1SWaldemar Kornewald
1786de2f76e1SWaldemar Kornewald
1787de2f76e1SWaldemar Kornewald bool
SendConfigureNak(net_buffer * packet)1788e3724c38Smshlyn KPPPStateMachine::SendConfigureNak(net_buffer *packet)
1789de2f76e1SWaldemar Kornewald {
179084b580c4SWaldemar Kornewald TRACE("KPPPSM: SendConfigureNak() state=%d phase=%d\n", State(), Phase());
17914e0ad752SWaldemar Kornewald
1792de2f76e1SWaldemar Kornewald if (!packet)
1793de2f76e1SWaldemar Kornewald return false;
1794de2f76e1SWaldemar Kornewald
1795e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1796e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1797e3724c38Smshlyn return false;
1798e3724c38Smshlyn ppp_lcp_packet &nak = bufferHeader.Data();
1799e3724c38Smshlyn
1800e3724c38Smshlyn if (nak.code == PPP_CONFIGURE_NAK) {
1801de2f76e1SWaldemar Kornewald if (fNakCounter == 0) {
1802de2f76e1SWaldemar Kornewald // We sent enough naks. Let's try a reject.
1803e3724c38Smshlyn nak.code = PPP_CONFIGURE_REJECT;
1804de2f76e1SWaldemar Kornewald } else
1805de2f76e1SWaldemar Kornewald --fNakCounter;
1806de2f76e1SWaldemar Kornewald }
1807de2f76e1SWaldemar Kornewald
1808de2f76e1SWaldemar Kornewald return LCP().Send(packet) == B_OK;
1809de2f76e1SWaldemar Kornewald }
1810de2f76e1SWaldemar Kornewald
1811de2f76e1SWaldemar Kornewald
1812de2f76e1SWaldemar Kornewald bool
SendTerminateRequest()1813f9ad2df8SWaldemar Kornewald KPPPStateMachine::SendTerminateRequest()
1814de2f76e1SWaldemar Kornewald {
181584b580c4SWaldemar Kornewald TRACE("KPPPSM: SendTerminateRequest() state=%d phase=%d\n", State(), Phase());
18164e0ad752SWaldemar Kornewald
18174e0ad752SWaldemar Kornewald --fTerminateCounter;
18186ff76cdaSWaldemar Kornewald fNextTimeout = system_time() + kPPPStateMachineTimeout;
18194e0ad752SWaldemar Kornewald
1820e3724c38Smshlyn net_buffer *buffer = gBufferModule->create(256);
1821e3724c38Smshlyn if (buffer == NULL)
1822e3724c38Smshlyn return false;
1823e3724c38Smshlyn
1824e3724c38Smshlyn ppp_lcp_packet *packet;
1825e3724c38Smshlyn status_t status = gBufferModule->append_size(buffer, 1492, (void **)&packet);
1826e3724c38Smshlyn if (status == B_OK && packet == NULL) {
1827e3724c38Smshlyn gBufferModule->free(buffer);
1828e3724c38Smshlyn return false;
1829e3724c38Smshlyn }
1830e3724c38Smshlyn
18314e0ad752SWaldemar Kornewald if (!packet)
1832de2f76e1SWaldemar Kornewald return false;
1833de2f76e1SWaldemar Kornewald
1834e3724c38Smshlyn packet->code = PPP_TERMINATE_REQUEST;
1835e3724c38Smshlyn packet->id = fTerminateID = NextID();
1836e3724c38Smshlyn packet->length = htons(4);
1837de2f76e1SWaldemar Kornewald
1838e3724c38Smshlyn status = gBufferModule->trim(buffer, 4);
1839e3724c38Smshlyn if (status < B_OK) {
1840e3724c38Smshlyn gBufferModule->free(buffer);
1841e3724c38Smshlyn return false;
1842e3724c38Smshlyn }
1843de2f76e1SWaldemar Kornewald
1844e3724c38Smshlyn return LCP().Send(buffer) == B_OK;
1845de2f76e1SWaldemar Kornewald }
1846de2f76e1SWaldemar Kornewald
1847de2f76e1SWaldemar Kornewald
1848de2f76e1SWaldemar Kornewald bool
SendTerminateAck(net_buffer * request)1849e3724c38Smshlyn KPPPStateMachine::SendTerminateAck(net_buffer *request)
1850de2f76e1SWaldemar Kornewald {
185184b580c4SWaldemar Kornewald TRACE("KPPPSM: SendTerminateAck() state=%d phase=%d\n", State(), Phase());
18524e0ad752SWaldemar Kornewald
1853e3724c38Smshlyn net_buffer *reply = request;
1854de2f76e1SWaldemar Kornewald
1855e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(request);
1856e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1857e3724c38Smshlyn return false;
1858e3724c38Smshlyn ppp_lcp_packet &ack = bufferHeader.Data();
1859de2f76e1SWaldemar Kornewald
1860de2f76e1SWaldemar Kornewald if (!reply) {
1861e3724c38Smshlyn ack.length = htons(4);
1862e3724c38Smshlyn ack.id = NextID();
1863e3724c38Smshlyn }
1864de2f76e1SWaldemar Kornewald
1865e3724c38Smshlyn ack.code = PPP_TERMINATE_ACK;
1866e3724c38Smshlyn ack.length = htons(4);
1867de2f76e1SWaldemar Kornewald
1868de2f76e1SWaldemar Kornewald return LCP().Send(reply) == B_OK;
1869de2f76e1SWaldemar Kornewald }
1870de2f76e1SWaldemar Kornewald
1871de2f76e1SWaldemar Kornewald
1872de2f76e1SWaldemar Kornewald bool
SendCodeReject(net_buffer * packet,uint16 protocolNumber,uint8 code)1873e3724c38Smshlyn KPPPStateMachine::SendCodeReject(net_buffer *packet, uint16 protocolNumber, uint8 code)
1874de2f76e1SWaldemar Kornewald {
187584b580c4SWaldemar Kornewald TRACE("KPPPSM: SendCodeReject(protocolNumber=%X;code=%d) state=%d phase=%d\n",
18764e0ad752SWaldemar Kornewald protocolNumber, code, State(), Phase());
18774e0ad752SWaldemar Kornewald
1878de2f76e1SWaldemar Kornewald if (!packet)
1879de2f76e1SWaldemar Kornewald return false;
1880de2f76e1SWaldemar Kornewald
1881de2f76e1SWaldemar Kornewald int32 length;
1882de2f76e1SWaldemar Kornewald // additional space needed for this reject
1883de2f76e1SWaldemar Kornewald if (code == PPP_PROTOCOL_REJECT)
1884de2f76e1SWaldemar Kornewald length = 6;
1885de2f76e1SWaldemar Kornewald else
1886de2f76e1SWaldemar Kornewald length = 4;
1887de2f76e1SWaldemar Kornewald
1888e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
1889e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1890e3724c38Smshlyn return false;
1891e3724c38Smshlyn ppp_lcp_packet &reject = bufferHeader.Data();
1892de2f76e1SWaldemar Kornewald
1893e3724c38Smshlyn reject.code = code;
1894e3724c38Smshlyn reject.id = NextID();
1895e3724c38Smshlyn reject.length = htons(length);
1896de2f76e1SWaldemar Kornewald
189792a8026eSWaldemar Kornewald protocolNumber = htons(protocolNumber);
1898de2f76e1SWaldemar Kornewald if (code == PPP_PROTOCOL_REJECT)
1899e3724c38Smshlyn memcpy(&reject.data, &protocolNumber, sizeof(protocolNumber));
1900de2f76e1SWaldemar Kornewald
1901de2f76e1SWaldemar Kornewald return LCP().Send(packet) == B_OK;
1902de2f76e1SWaldemar Kornewald }
1903de2f76e1SWaldemar Kornewald
1904de2f76e1SWaldemar Kornewald
1905de2f76e1SWaldemar Kornewald bool
SendEchoReply(net_buffer * request)1906e3724c38Smshlyn KPPPStateMachine::SendEchoReply(net_buffer *request)
1907de2f76e1SWaldemar Kornewald {
190884b580c4SWaldemar Kornewald TRACE("KPPPSM: SendEchoReply() state=%d phase=%d\n", State(), Phase());
19094e0ad752SWaldemar Kornewald
1910de2f76e1SWaldemar Kornewald if (!request)
1911de2f76e1SWaldemar Kornewald return false;
1912de2f76e1SWaldemar Kornewald
1913e3724c38Smshlyn NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(request);
1914e3724c38Smshlyn if (bufferHeader.Status() < B_OK)
1915e3724c38Smshlyn return false;
1916e3724c38Smshlyn ppp_lcp_packet &reply = bufferHeader.Data();
1917e3724c38Smshlyn
1918e3724c38Smshlyn reply.code = PPP_ECHO_REPLY;
1919de2f76e1SWaldemar Kornewald // the request becomes a reply
1920de2f76e1SWaldemar Kornewald
1921e3724c38Smshlyn memcpy(reply.data, &fMagicNumber, sizeof(fMagicNumber));
1922de2f76e1SWaldemar Kornewald
1923de2f76e1SWaldemar Kornewald return LCP().Send(request) == B_OK;
1924de2f76e1SWaldemar Kornewald }
1925de2f76e1SWaldemar Kornewald
1926de2f76e1SWaldemar Kornewald
192792a8026eSWaldemar Kornewald // methods for bringing protocols up
1928de2f76e1SWaldemar Kornewald void
BringProtocolsUp()1929f9ad2df8SWaldemar Kornewald KPPPStateMachine::BringProtocolsUp()
1930de2f76e1SWaldemar Kornewald {
1931de2f76e1SWaldemar Kornewald // use a simple check for phase changes (e.g., caused by CloseEvent())
1932de2f76e1SWaldemar Kornewald while (Phase() <= PPP_ESTABLISHED_PHASE && Phase() >= PPP_AUTHENTICATION_PHASE) {
1933de2f76e1SWaldemar Kornewald if (BringPhaseUp() > 0)
1934de2f76e1SWaldemar Kornewald break;
1935de2f76e1SWaldemar Kornewald
1936de2f76e1SWaldemar Kornewald if (Phase() < PPP_AUTHENTICATION_PHASE)
1937de2f76e1SWaldemar Kornewald return;
1938de2f76e1SWaldemar Kornewald // phase was changed by another event
1939de2f76e1SWaldemar Kornewald else if (Phase() == PPP_ESTABLISHED_PHASE) {
1940de2f76e1SWaldemar Kornewald if (Interface().Parent())
1941de2f76e1SWaldemar Kornewald Interface().Parent()->StateMachine().UpEvent(Interface());
194293a59056SWaldemar Kornewald break;
1943de2f76e1SWaldemar Kornewald } else
1944de2f76e1SWaldemar Kornewald NewPhase((ppp_phase) (Phase() + 1));
1945de2f76e1SWaldemar Kornewald }
1946de2f76e1SWaldemar Kornewald }
1947de2f76e1SWaldemar Kornewald
1948de2f76e1SWaldemar Kornewald
1949de2f76e1SWaldemar Kornewald // this returns the number of handlers waiting to go up
1950de2f76e1SWaldemar Kornewald uint32
BringPhaseUp()1951f9ad2df8SWaldemar Kornewald KPPPStateMachine::BringPhaseUp()
1952de2f76e1SWaldemar Kornewald {
1953ca43389aSWaldemar Kornewald // Servers do not need to bring all protocols up.
1954ca43389aSWaldemar Kornewald // The client specifies which protocols he wants to go up.
1955ca43389aSWaldemar Kornewald
1956de2f76e1SWaldemar Kornewald // check for phase change
1957de2f76e1SWaldemar Kornewald if (Phase() < PPP_AUTHENTICATION_PHASE)
1958de2f76e1SWaldemar Kornewald return 0;
1959de2f76e1SWaldemar Kornewald
1960de2f76e1SWaldemar Kornewald uint32 count = 0;
1961f9ad2df8SWaldemar Kornewald KPPPProtocol *protocol = Interface().FirstProtocol();
196292a8026eSWaldemar Kornewald for (; protocol; protocol = protocol->NextProtocol()) {
196392a8026eSWaldemar Kornewald if (protocol->IsEnabled() && protocol->ActivationPhase() == Phase()) {
1964ca43389aSWaldemar Kornewald if (protocol->IsGoingUp() && Interface().Mode() == PPP_CLIENT_MODE)
1965de2f76e1SWaldemar Kornewald ++count;
1966ca43389aSWaldemar Kornewald else if (protocol->IsDown() && protocol->IsUpRequested()) {
1967ca43389aSWaldemar Kornewald if (Interface().Mode() == PPP_CLIENT_MODE)
1968ca43389aSWaldemar Kornewald ++count;
1969ca43389aSWaldemar Kornewald
197092a8026eSWaldemar Kornewald protocol->Up();
1971ca43389aSWaldemar Kornewald }
1972ca43389aSWaldemar Kornewald }
1973ca43389aSWaldemar Kornewald }
1974ca43389aSWaldemar Kornewald
1975ca43389aSWaldemar Kornewald // We only wait until authentication is complete.
1976ca43389aSWaldemar Kornewald if (Interface().Mode() == PPP_SERVER_MODE
1977ca43389aSWaldemar Kornewald && (LocalAuthenticationStatus() == PPP_AUTHENTICATING
1978ca43389aSWaldemar Kornewald || PeerAuthenticationStatus() == PPP_AUTHENTICATING))
1979de2f76e1SWaldemar Kornewald ++count;
1980de2f76e1SWaldemar Kornewald
1981de2f76e1SWaldemar Kornewald return count;
1982de2f76e1SWaldemar Kornewald }
1983de2f76e1SWaldemar Kornewald
1984de2f76e1SWaldemar Kornewald
1985de2f76e1SWaldemar Kornewald void
DownProtocols()1986f9ad2df8SWaldemar Kornewald KPPPStateMachine::DownProtocols()
1987de2f76e1SWaldemar Kornewald {
1988f9ad2df8SWaldemar Kornewald KPPPProtocol *protocol = Interface().FirstProtocol();
1989de2f76e1SWaldemar Kornewald
199092a8026eSWaldemar Kornewald for (; protocol; protocol = protocol->NextProtocol())
199192a8026eSWaldemar Kornewald if (protocol->IsEnabled())
199292a8026eSWaldemar Kornewald protocol->Down();
1993de2f76e1SWaldemar Kornewald }
1994de2f76e1SWaldemar Kornewald
1995de2f76e1SWaldemar Kornewald
1996de2f76e1SWaldemar Kornewald void
ResetLCPHandlers()1997f9ad2df8SWaldemar Kornewald KPPPStateMachine::ResetLCPHandlers()
1998de2f76e1SWaldemar Kornewald {
1999de2f76e1SWaldemar Kornewald for (int32 index = 0; index < LCP().CountOptionHandlers(); index++)
2000de2f76e1SWaldemar Kornewald LCP().OptionHandlerAt(index)->Reset();
2001de2f76e1SWaldemar Kornewald
2002de2f76e1SWaldemar Kornewald for (int32 index = 0; index < LCP().CountLCPExtensions(); index++)
2003de2f76e1SWaldemar Kornewald LCP().LCPExtensionAt(index)->Reset();
2004de2f76e1SWaldemar Kornewald }
2005