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