xref: /haiku/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp (revision 7e66a28740b80bf87c3f91cbb9b7b58ff4ef7f0e)
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