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