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