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