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