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