xref: /haiku/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp (revision 7e66a28740b80bf87c3f91cbb9b7b58ff4ef7f0e)
1 /*
2  * Copyright 2003-2007, Waldemar Kornewald <wkornew@gmx.net>
3  * Distributed under the terms of the MIT License.
4  */
5 
6 /*!	\class KPPPInterface
7 	\brief The kernel representation of a PPP interface.
8 
9 	This class is never created by the programmer directly. Instead, the PPP manager
10 	kernel module should be used. \n
11 	KPPPInterface handles all interface-specific commands from userspace and it
12 	passes packets to their receiver or sends them to the device. Additionally,
13 	it contains the KPPPLCP object with represents the LCP protocol and the
14 	KPPPStateMachine object which represents the state machine. \n
15 	All PPP modules are loaded from here. \n
16 	Protocols and encapsulators should be added to this class. LCP-specific extensions
17 	belong to the KPPPLCP object. \n
18 	Multilink support is distributed between KPPPInterface and KPPPStateMachine.
19 */
20 
21 // cstdio must be included before KPPPModule.h/KPPPManager.h because
22 // dprintf is defined twice with different return values, once with
23 // void (KernelExport.h) and once with int (stdio.h).
24 #include <cstdio>
25 #include <cstring>
26 #include <arpa/inet.h>
27 
28 #include <ByteOrder.h>
29 #include <net_buffer.h>
30 #include <net_stack.h>
31 #include <ppp_device.h>
32 
33 // now our headers...
34 #include <KPPPInterface.h>
35 
36 // our other classes
37 #include <PPPControl.h>
38 #include <KPPPDevice.h>
39 #include <KPPPLCPExtension.h>
40 #include <KPPPOptionHandler.h>
41 #include <KPPPModule.h>
42 #include <KPPPManager.h>
43 #include <KPPPUtils.h>
44 
45 // general helper classes not only belonging to us
46 // #include <lock.h>
47 // #include <util/AutoLock.h>
48 
49 // tools only for us :)
50 #include "settings_tools.h"
51 
52 // internal modules
53 #include "_KPPPMRUHandler.h"
54 #include "_KPPPAuthenticationHandler.h"
55 #include "_KPPPPFCHandler.h"
56 
57 
58 // TODO:
59 // - implement timers with support for setting next event instead of receiving timer
60 //    events periodically
61 // - add missing settings support (ConnectRetryDelay, etc.)
62 
63 
64 //!	Private structure needed for reconnecting.
65 typedef struct reconnect_info {
66 	KPPPInterface *interface;
67 	thread_id *thread;
68 	uint32 delay;
69 } reconnect_info;
70 
71 extern net_buffer_module_info *gBufferModule;
72 extern net_stack_module_info *gStackModule;
73 
74 status_t reconnect_thread(void *data);
75 
76 // other functions
77 status_t interface_deleter_thread(void *data);
78 
79 
80 /*!	\brief Creates a new interface.
81 
82 	\param name Name of the PPP interface description file.
83 	\param entry The PPP manager passes an internal structure to the constructor.
84 	\param ID The interface's ID.
85 	\param settings (Optional): If no name is given you must pass the settings here.
86 	\param parent (Optional): Interface's parent (only used for multilink interfaces).
87 */
KPPPInterface(const char * name,ppp_interface_entry * entry,ppp_interface_id ID,const driver_settings * settings,KPPPInterface * parent)88 KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry,
89 	ppp_interface_id ID, const driver_settings *settings, KPPPInterface *parent)
90 	:
91 	KPPPLayer(name, PPP_INTERFACE_LEVEL, 2),
92 	fID(ID),
93 	fSettings(NULL),
94 	fIfnet(NULL),
95 	fReconnectThread(-1),
96 	fConnectAttempt(1),
97 	fConnectRetriesLimit(0),
98 	fManager(NULL),
99 	fConnectedSince(0),
100 	fIdleSince(0),
101 	fMRU(1500),
102 	fInterfaceMTU(1498),
103 	fHeaderLength(2),
104 	fParent(NULL),
105 	fIsMultilink(false),
106 	fAutoReconnect(false),
107 	fConnectOnDemand(true),
108 	fAskBeforeConnecting(false),
109 	fMode(PPP_CLIENT_MODE),
110 	fLocalPFCState(PPP_PFC_DISABLED),
111 	fPeerPFCState(PPP_PFC_DISABLED),
112 	fPFCOptions(0),
113 	fDevice(NULL),
114 	fFirstProtocol(NULL),
115 	fStateMachine(*this),
116 	fLCP(*this),
117 	fReportManager(StateMachine().fLock),
118 	fLock(StateMachine().fLock),
119 	fDeleteCounter(0)
120 {
121 	entry->interface = this;
122 
123 	if (name) {
124 		// load settings from description file
125 		char path[B_PATH_NAME_LENGTH];
126 		sprintf(path, "ptpnet/%s", name);
127 
128 		void *handle = load_driver_settings(path);
129 		if (!handle) {
130 			ERROR("KPPPInterface: Unable to load %s PPP driver settings!\n", path);
131 			fInitStatus = B_ERROR;
132 			return;
133 		}
134 
135 		fSettings = dup_driver_settings(get_driver_settings(handle));
136 		unload_driver_settings(handle);
137 	} else
138 		fSettings = dup_driver_settings(settings);
139 			// use the given settings
140 
141 	if (!fSettings) {
142 		ERROR("KPPPInterface: No fSettings!\n");
143 		fInitStatus = B_ERROR;
144 		return;
145 	}
146 
147 	// add internal modules
148 	// LCP
149 	if (!AddProtocol(&LCP())) {
150 		ERROR("KPPPInterface: Could not add LCP protocol!\n");
151 		fInitStatus = B_ERROR;
152 		return;
153 	}
154 	// MRU
155 	_KPPPMRUHandler *mruHandler =
156 		new _KPPPMRUHandler(*this);
157 	if (!LCP().AddOptionHandler(mruHandler) || mruHandler->InitCheck() != B_OK) {
158 		ERROR("KPPPInterface: Could not add MRU handler!\n");
159 		delete mruHandler;
160 	}
161 	// authentication
162 	_KPPPAuthenticationHandler *authenticationHandler =
163 		new _KPPPAuthenticationHandler(*this);
164 	if (!LCP().AddOptionHandler(authenticationHandler)
165 			|| authenticationHandler->InitCheck() != B_OK) {
166 		ERROR("KPPPInterface: Could not add authentication handler!\n");
167 		delete authenticationHandler;
168 	}
169 	// PFC
170 	_KPPPPFCHandler *pfcHandler =
171 		new _KPPPPFCHandler(fLocalPFCState, fPeerPFCState, *this);
172 	if (!LCP().AddOptionHandler(pfcHandler) || pfcHandler->InitCheck() != B_OK) {
173 		ERROR("KPPPInterface: Could not add PFC handler!\n");
174 		delete pfcHandler;
175 	}
176 
177 	// set up connect delays
178 	fConnectRetryDelay = 3000;
179 		// 3s delay between each new attempt to reconnect
180 	fReconnectDelay = 1000;
181 		// 1s delay between lost connection and reconnect
182 
183 	if (get_module(PPP_INTERFACE_MODULE_NAME, (module_info**) &fManager) != B_OK)
184 		ERROR("KPPPInterface: Manager module not found!\n");
185 
186 	// are we a multilink subinterface?
187 	if (parent && parent->IsMultilink()) {
188 		fParent = parent;
189 		fParent->AddChild(this);
190 		fIsMultilink = true;
191 	}
192 
193 	RegisterInterface();
194 
195 	if (!fSettings) {
196 		fInitStatus = B_ERROR;
197 		return;
198 	}
199 
200 	const char *value;
201 
202 	// get login
203 	value = get_settings_value(PPP_USERNAME_KEY, fSettings);
204 	fUsername = value ? strdup(value) : strdup("");
205 	value = get_settings_value(PPP_PASSWORD_KEY, fSettings);
206 	fPassword = value ? strdup(value) : strdup("");
207 
208 	// get DisonnectAfterIdleSince settings
209 	value = get_settings_value(PPP_DISONNECT_AFTER_IDLE_SINCE_KEY, fSettings);
210 	if (!value)
211 		fDisconnectAfterIdleSince = 0;
212 	else
213 		fDisconnectAfterIdleSince = atoi(value) * 1000;
214 
215 	if (fDisconnectAfterIdleSince < 0)
216 		fDisconnectAfterIdleSince = 0;
217 
218 	// get mode settings
219 	value = get_settings_value(PPP_MODE_KEY, fSettings);
220 	if (value && !strcasecmp(value, PPP_SERVER_MODE_VALUE))
221 		fMode = PPP_SERVER_MODE;
222 	else
223 		fMode = PPP_CLIENT_MODE;
224 		// we are a client by default
225 
226 	SetAutoReconnect(
227 		get_boolean_value(
228 		get_settings_value(PPP_AUTO_RECONNECT_KEY, fSettings),
229 		false)
230 		);
231 		// auto reconnect is disabled by default
232 
233 	fAskBeforeConnecting = get_boolean_value(
234 		get_settings_value(PPP_ASK_BEFORE_CONNECTING_KEY, fSettings), false);
235 
236 	// load all protocols and the device
237 	if (!LoadModules(fSettings, 0, fSettings->parameter_count)) {
238 		ERROR("KPPPInterface: Error loading modules!\n");
239 		fInitStatus = B_ERROR;
240 	}
241 }
242 
243 
244 //!	Destructor: Disconnects and marks interface for deletion.
~KPPPInterface()245 KPPPInterface::~KPPPInterface()
246 {
247 	TRACE("KPPPInterface: Destructor\n");
248 
249 	// tell protocols to uninit (remove routes, etc.)
250 	KPPPProtocol *protocol = FirstProtocol();
251 	for (; protocol; protocol = protocol->NextProtocol())
252 		protocol->Uninit();
253 
254 	// make sure we are not accessible by any thread before we continue
255 	UnregisterInterface();
256 
257 	if (fManager)
258 		fManager->RemoveInterface(ID());
259 
260 	// Call Down() until we get a lock on an interface that is down.
261 	// This lock is not released until we are actually deleted.
262 	while (true) {
263 		Down();
264 		{
265 			MutexLocker locker(fLock);
266 			if (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE)
267 				break;
268 		}
269 	}
270 
271 	Report(PPP_DESTRUCTION_REPORT, 0, &fID, sizeof(ppp_interface_id));
272 		// tell all listeners that we are being destroyed
273 
274 	int32 tmp;
275 	send_data_with_timeout(fReconnectThread, 0, NULL, 0, 200);
276 		// tell thread that we are being destroyed (200ms timeout)
277 	wait_for_thread(fReconnectThread, &tmp);
278 
279 	while (CountChildren())
280 		delete ChildAt(0);
281 
282 	delete Device();
283 
284 	while (FirstProtocol()) {
285 		if (FirstProtocol() == &LCP())
286 			fFirstProtocol = fFirstProtocol->NextProtocol();
287 		else
288 			delete FirstProtocol();
289 				// destructor removes protocol from list
290 	}
291 
292 	for (int32 index = 0; index < fModules.CountItems(); index++) {
293 		put_module(fModules.ItemAt(index));
294 		delete[] fModules.ItemAt(index);
295 	}
296 
297 	free_driver_settings(fSettings);
298 
299 	if (Parent())
300 		Parent()->RemoveChild(this);
301 
302 	if (fManager)
303 		put_module(PPP_INTERFACE_MODULE_NAME);
304 }
305 
306 
307 //!	Marks interface for deletion.
308 void
Delete()309 KPPPInterface::Delete()
310 {
311 	// MutexLocker locker(fLock);
312 		// alreay locked in KPPPStatemachine::DownEvent
313 		// uncomment this line will cause double lock
314 
315 	if (fDeleteCounter > 0)
316 		return;
317 			// only one thread should delete us!
318 
319 	fDeleteCounter = 1;
320 
321 	fManager->DeleteInterface(ID());
322 		// This will mark us for deletion.
323 		// Any subsequent calls to delete_interface() will do nothing.
324 }
325 
326 
327 //!	Returns if interface was initialized correctly.
328 status_t
InitCheck() const329 KPPPInterface::InitCheck() const
330 {
331 	if (fInitStatus != B_OK)
332 		return fInitStatus;
333 
334 	if (!fSettings || !fManager)
335 		return B_ERROR;
336 
337 	// sub-interfaces should have a device
338 	if (IsMultilink()) {
339 		if (Parent() && !fDevice)
340 			return B_ERROR;
341 	} else if (!fDevice)
342 		return B_ERROR;
343 
344 	return B_OK;
345 }
346 
347 
348 //!	The username used for authentication.
349 const char*
Username() const350 KPPPInterface::Username() const
351 {
352 	// this data is not available before we authenticate
353 	if (Phase() < PPP_AUTHENTICATION_PHASE)
354 		return NULL;
355 
356 	return fUsername;
357 }
358 
359 
360 //!	The password used for authentication.
361 const char*
Password() const362 KPPPInterface::Password() const
363 {
364 	// this data is not available before we authenticate
365 	if (Phase() < PPP_AUTHENTICATION_PHASE)
366 		return NULL;
367 
368 	return fPassword;
369 }
370 
371 
372 //!	Sets interface MRU.
373 bool
SetMRU(uint32 MRU)374 KPPPInterface::SetMRU(uint32 MRU)
375 {
376 	TRACE("KPPPInterface: SetMRU(%ld)\n", MRU);
377 
378 	if (Device() && MRU > Device()->MTU() - 2)
379 		return false;
380 
381 	// MutexLocker locker(fLock);
382 		// uncomment this line will cause double lock
383 		// alreay locked in ::Up and ::KPPPInterface
384 
385 	fMRU = MRU;
386 
387 	CalculateInterfaceMTU();
388 
389 	return true;
390 }
391 
392 
393 //!	Returns number of bytes spent for protocol overhead. Includes device overhead.
394 uint32
PacketOverhead() const395 KPPPInterface::PacketOverhead() const
396 {
397 	uint32 overhead = fHeaderLength + 2;
398 
399 	if (Device())
400 		overhead += Device()->Overhead();
401 
402 	return overhead;
403 }
404 
405 
406 /*!	\brief Allows accessing additional functions.
407 
408 	This is normally called by userland apps to get information about the interface.
409 
410 	\param op The op value (see ppp_control_ops enum).
411 	\param data (Optional): Additional data may be needed for this op.
412 	\param length Length of data.
413 
414 	\return
415 		- \c B_OK: \c Control() was successful.
416 		- \c B_ERROR: Either \a length is too small or data is NULL.
417 		- \c B_NOT_ALLOWED: Operation not allowed (at this point in time).
418 		- \c B_BAD_INDEX: Wrong index (e.g.: when accessing interface submodules).
419 		- \c B_BAD_VALUE: Unknown op.
420 		- Return value of submodule (when controlling one).
421 */
422 status_t
Control(uint32 op,void * data,size_t length)423 KPPPInterface::Control(uint32 op, void *data, size_t length)
424 {
425 	TRACE("%s:%s\n", __FILE__, __func__);
426 
427         control_net_module_args* args = (control_net_module_args*)data;
428         if (op != NET_STACK_CONTROL_NET_MODULE) {
429 		dprintf("unknow op!!\n");
430 		return B_BAD_VALUE;
431 	}
432 
433 	switch (args->op) {
434 		case PPPC_COUNT_INTERFACES:
435 		{
436 			// should be implepented
437 			dprintf("PPPC_COUNT_INTERFACES should be implepentd\n");
438 
439 			return B_OK;
440 		}
441 
442 		case PPPC_GET_INTERFACES:
443 		{
444 			dprintf("PPPC_GET_INTERFACES\n");
445 			ppp_get_interfaces_info* info = (ppp_get_interfaces_info*)args->data;
446 			dprintf("info->interfaces: %p\n", info->interfaces);
447 			*(info->interfaces) = 1;
448 			info->resultCount = 1;
449 
450 			return B_OK;
451 		}
452 
453 		case PPPC_CONTROL_INTERFACE:
454 		{
455 			dprintf("PPPC_CONTROL_INTERFACE\n");
456 			ppp_control_info* control = (ppp_control_info*)args->data;
457 
458 			switch (control->op) {
459 			case PPPC_GET_INTERFACE_INFO:
460 			{
461 				dprintf("PPPC_GET_INTERFACE_INFO\n");
462 				if (control->length < sizeof(ppp_interface_info_t) || !control->data) {
463 					dprintf("size wrong!\n");
464 					return B_ERROR;
465 				}
466 
467 				ppp_interface_info *info = (ppp_interface_info*) control->data;
468 				dprintf("info addr:%p\n", info);
469 				memset(info, 0, sizeof(ppp_interface_info_t));
470 				if (Name())
471 					strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT);
472 
473 				if (Ifnet())
474 					info->if_unit = Ifnet()->index;
475 				else
476 					info->if_unit = -1;
477 				info->mode = Mode();
478 				info->state = State();
479 				info->phase = Phase();
480 				info->localAuthenticationStatus =
481 					StateMachine().LocalAuthenticationStatus();
482 				info->peerAuthenticationStatus =
483 					StateMachine().PeerAuthenticationStatus();
484 				info->localPFCState = LocalPFCState();
485 				info->peerPFCState = PeerPFCState();
486 				info->pfcOptions = PFCOptions();
487 				info->protocolsCount = CountProtocols();
488 				info->optionHandlersCount = LCP().CountOptionHandlers();
489 				info->LCPExtensionsCount = 0;
490 				info->childrenCount = CountChildren();
491 				info->MRU = MRU();
492 				info->interfaceMTU = InterfaceMTU();
493 				info->connectAttempt = fConnectAttempt;
494 				info->connectRetriesLimit = fConnectRetriesLimit;
495 				info->connectRetryDelay = ConnectRetryDelay();
496 				info->reconnectDelay = ReconnectDelay();
497 				info->connectedSince = ConnectedSince();
498 				info->idleSince = IdleSince();
499 				info->disconnectAfterIdleSince = DisconnectAfterIdleSince();
500 				info->doesConnectOnDemand = DoesConnectOnDemand();
501 				info->doesAutoReconnect = DoesAutoReconnect();
502 				info->hasDevice = Device();
503 				info->isMultilink = IsMultilink();
504 				info->hasParent = Parent();
505 				break;
506 			}
507 
508 			case PPPC_SET_USERNAME:
509 			{
510 				dprintf("PPPC_SET_USERNAME\n");
511 				if (control->length > PPP_HANDLER_NAME_LENGTH_LIMIT || !control->data) {
512 					dprintf("size wrong!\n");
513 					return B_ERROR;
514 				}
515 
516 				MutexLocker locker(fLock);
517 				// login information can only be changed before we authenticate
518 				if (Phase() >= PPP_AUTHENTICATION_PHASE)
519 					return B_NOT_ALLOWED;
520 
521 				free(fUsername);
522 				fUsername = control->data ? strdup((const char*) control->data) : strdup("");
523 				dprintf("set ppp user name to %s\n", fUsername);
524 
525 				break;
526 			}
527 
528 			case PPPC_SET_PASSWORD:
529 			{
530 				dprintf("PPPC_SET_PASSWORD\n");
531 				if (control->length > PPP_HANDLER_NAME_LENGTH_LIMIT || !control->data) {
532 					dprintf("size wrong!\n");
533 					return B_ERROR;
534 				}
535 
536 				MutexLocker locker(fLock);
537 				// login information can only be changed before we authenticate
538 				if (Phase() >= PPP_AUTHENTICATION_PHASE)
539 					return B_NOT_ALLOWED;
540 
541 				free(fPassword);
542 				fPassword = control->data ? strdup((const char*) control->data) : strdup("");
543 				dprintf("set ppp password to %s!\n", fPassword);
544 				break;
545 			}
546 
547 			case PPPC_SET_ASK_BEFORE_CONNECTING:
548 			{
549 				dprintf("PPPC_SET_ASK_BEFORE_CONNECTING\n");
550 				if (control->length < sizeof(uint32) || !control->data) {
551 					dprintf("size wrong!\n");
552 					return B_ERROR;
553 				}
554 
555 				SetAskBeforeConnecting(*((uint32*)control->data));
556 				dprintf("goto PPPC_SET_ASK_BEFORE_CONNECTING here!\n");
557 				break;
558 			}
559 
560 			case PPPC_GET_STATISTICS:
561 			{
562 				dprintf("PPPC_GET_STATISTICS\n");
563 				if (control->length < sizeof(ppp_statistics) || !control->data) {
564 					dprintf("size wrong!\n");
565 					return B_ERROR;
566 				}
567 
568 				dprintf("should PPPC_GET_STATISTICS here!\n");
569 
570 				memcpy(control->data, &fStatistics, sizeof(ppp_statistics));
571 				break;
572 			}
573 
574 			case PPPC_HAS_INTERFACE_SETTINGS:
575 			{
576 				dprintf("PPPC_HAS_INTERFACE_SETTINGS\n");
577 				if (control->length < sizeof(driver_settings) || !control->data) {
578 					dprintf("size wrong!\n");
579 					return B_ERROR;
580 				}
581 
582 				dprintf("should PPPC_HAS_INTERFACE_SETTINGS here!\n");
583 
584 				if (equal_interface_settings(Settings(), (driver_settings*)control->data))
585 					return B_OK;
586 				else
587 					return B_ERROR;
588 				break;
589 
590 			}
591 
592 			case PPPC_ENABLE_REPORTS:
593 			{
594 				dprintf("PPPC_ENABLE_REPORTS\n");
595 				if (control->length < sizeof(ppp_report_request) || !control->data) {
596 					dprintf("size wrong!\n");
597 					return B_ERROR;
598 				}
599 
600 				dprintf("should PPPC_ENABLE_REPORTS here!\n");
601 
602 				MutexLocker locker(fLock);
603 				ppp_report_request *request = (ppp_report_request*) control->data;
604 				// first, we send an initial state report
605 				if (request->type == PPP_CONNECTION_REPORT) {
606 					ppp_report_packet report;
607 					report.type = PPP_CONNECTION_REPORT;
608 					report.code = StateMachine().fLastConnectionReportCode;
609 					report.length = sizeof(fID);
610 					KPPPReportManager::SendReport(request->thread, &report);
611 					if (request->flags & PPP_REMOVE_AFTER_REPORT)
612 						return B_OK;
613 				}
614 				ReportManager().EnableReports(request->type, request->thread,
615 					request->flags);
616 				break;
617 			}
618 
619 			case PPPC_DISABLE_REPORTS:
620 			{
621 				dprintf("PPPC_DISABLE_REPORTS\n");
622 				if (control->length < sizeof(ppp_report_request) || !control->data) {
623 					dprintf("size wrong!\n");
624 					return B_ERROR;
625 				}
626 
627 				dprintf("should PPPC_DISABLE_REPORTS here!\n");
628 
629 				ppp_report_request *request = (ppp_report_request*) control->data;
630 				ReportManager().DisableReports(request->type, request->thread);
631 				break;
632 			}
633 
634 			case PPPC_CONTROL_DEVICE:
635 			{
636 				dprintf("PPPC_CONTROL_DEVICE\n");
637 				if (control->length < sizeof(ppp_control_info) || !control->data)
638 					return B_ERROR;
639 
640 				ppp_control_info *controlInfo = (ppp_control_info*) control->data;
641 				if (controlInfo->index != 0 || !Device()) {
642 					dprintf("index is 0 or no Device\n");
643 					return B_BAD_INDEX;
644 				}
645 
646 				return Device()->Control(controlInfo->op, controlInfo->data, controlInfo->length);
647 			}
648 
649 			case PPPC_CONTROL_PROTOCOL:
650 			{
651 				dprintf("PPPC_CONTROL_PROTOCOL\n");
652 				if (control->length < sizeof(ppp_control_info) || !control->data)
653 					return B_ERROR;
654 
655 				ppp_control_info *controlInfo = (ppp_control_info*) control->data;
656 				KPPPProtocol *protocol = ProtocolAt(controlInfo->index);
657 				if (!protocol)
658 					return B_BAD_INDEX;
659 
660 				return protocol->Control(controlInfo->op, controlInfo->data, controlInfo->length);
661 			}
662 
663 			case PPPC_CONTROL_OPTION_HANDLER:
664 			{
665 				dprintf("PPPC_CONTROL_OPTION_HANDLER\n");
666 				if (control->length < sizeof(ppp_control_info) || !control->data)
667 					return B_ERROR;
668 
669 				ppp_control_info *controlInfo = (ppp_control_info*) control->data;
670 				KPPPOptionHandler *optionHandler = LCP().OptionHandlerAt(controlInfo->index);
671 				if (!optionHandler) {
672 					dprintf("optionHandler no avail\n");
673 					return B_BAD_INDEX;
674 				}
675 
676 				return optionHandler->Control(controlInfo->op, controlInfo->data,
677 					controlInfo->length);
678 			}
679 
680 			case PPPC_CONTROL_LCP_EXTENSION:
681 			{
682 				dprintf("PPPC_CONTROL_LCP_EXTENSION\n");
683 				if (control->length < sizeof(ppp_control_info) || !control->data)
684 					return B_ERROR;
685 
686 				ppp_control_info *controlInfo = (ppp_control_info*) control->data;
687 				KPPPLCPExtension *lcpExtension = LCP().LCPExtensionAt(controlInfo->index);
688 				if (!lcpExtension)
689 					return B_BAD_INDEX;
690 
691 				return lcpExtension->Control(controlInfo->op, controlInfo->data,
692 					controlInfo->length);
693 			}
694 
695 			case PPPC_CONTROL_CHILD:
696 			{
697 				dprintf("PPPC_CONTROL_CHILD\n");
698 				if (control->length < sizeof(ppp_control_info) || !control->data)
699 					return B_ERROR;
700 
701 				ppp_control_info *controlInfo = (ppp_control_info*) control->data;
702 				KPPPInterface *child = ChildAt(controlInfo->index);
703 				if (!child)
704 					return B_BAD_INDEX;
705 
706 				return child->Control(controlInfo->op, controlInfo->data, controlInfo->length);
707 			}
708 
709 			default :
710 				return B_ERROR;
711 		}
712 
713 			return B_OK;
714 		}
715 
716 		case PPPC_GET_INTERFACE_INFO:
717 		{
718 			if (length < sizeof(ppp_interface_info_t) || !data)
719 				return B_ERROR;
720 
721 			ppp_interface_info *info = (ppp_interface_info*) data;
722 			memset(info, 0, sizeof(ppp_interface_info_t));
723 			if (Name())
724 				strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT);
725 			if (Ifnet())
726 				info->if_unit = Ifnet()->index;
727 			else
728 				info->if_unit = -1;
729 			info->mode = Mode();
730 			info->state = State();
731 			info->phase = Phase();
732 			info->localAuthenticationStatus =
733 				StateMachine().LocalAuthenticationStatus();
734 			info->peerAuthenticationStatus =
735 				StateMachine().PeerAuthenticationStatus();
736 			info->localPFCState = LocalPFCState();
737 			info->peerPFCState = PeerPFCState();
738 			info->pfcOptions = PFCOptions();
739 			info->protocolsCount = CountProtocols();
740 			info->optionHandlersCount = LCP().CountOptionHandlers();
741 			info->LCPExtensionsCount = 0;
742 			info->childrenCount = CountChildren();
743 			info->MRU = MRU();
744 			info->interfaceMTU = InterfaceMTU();
745 			info->connectAttempt = fConnectAttempt;
746 			info->connectRetriesLimit = fConnectRetriesLimit;
747 			info->connectRetryDelay = ConnectRetryDelay();
748 			info->reconnectDelay = ReconnectDelay();
749 			info->connectedSince = ConnectedSince();
750 			info->idleSince = IdleSince();
751 			info->disconnectAfterIdleSince = DisconnectAfterIdleSince();
752 			info->doesConnectOnDemand = DoesConnectOnDemand();
753 			info->doesAutoReconnect = DoesAutoReconnect();
754 			info->hasDevice = Device();
755 			info->isMultilink = IsMultilink();
756 			info->hasParent = Parent();
757 			break;
758 		}
759 
760 		case PPPC_SET_USERNAME:
761 		{
762 			if (!data)
763 				return B_ERROR;
764 
765 			MutexLocker locker(fLock);
766 			// login information can only be changed before we authenticate
767 			if (Phase() >= PPP_AUTHENTICATION_PHASE)
768 				return B_NOT_ALLOWED;
769 
770 			free(fUsername);
771 			fUsername = data ? strdup((const char*) data) : strdup("");
772 			break;
773 		}
774 
775 		case PPPC_SET_PASSWORD:
776 		{
777 			if (!data)
778 				return B_ERROR;
779 
780 			MutexLocker locker(fLock);
781 			// login information can only be changed before we authenticate
782 			if (Phase() >= PPP_AUTHENTICATION_PHASE)
783 				return B_NOT_ALLOWED;
784 
785 			free(fPassword);
786 			fPassword = data ? strdup((const char*) data) : strdup("");
787 			break;
788 		}
789 
790 		case PPPC_SET_ASK_BEFORE_CONNECTING:
791 			if (length < sizeof(uint32) || !data)
792 				return B_ERROR;
793 
794 			SetAskBeforeConnecting(*((uint32*)data));
795 			break;
796 
797 		case PPPC_SET_MRU:
798 			if (length < sizeof(uint32) || !data)
799 				return B_ERROR;
800 
801 			SetMRU(*((uint32*)data));
802 			break;
803 
804 		case PPPC_SET_CONNECT_ON_DEMAND:
805 			if (length < sizeof(uint32) || !data)
806 				return B_ERROR;
807 
808 			SetConnectOnDemand(*((uint32*)data));
809 			break;
810 
811 		case PPPC_SET_AUTO_RECONNECT:
812 			if (length < sizeof(uint32) || !data)
813 				return B_ERROR;
814 
815 			SetAutoReconnect(*((uint32*)data));
816 			break;
817 
818 		case PPPC_HAS_INTERFACE_SETTINGS:
819 			if (length < sizeof(driver_settings) || !data)
820 				return B_ERROR;
821 
822 			if (equal_interface_settings(Settings(), (driver_settings*) data))
823 				return B_OK;
824 			else
825 				return B_ERROR;
826 			break;
827 
828 		case PPPC_ENABLE_REPORTS:
829 		{
830 			if (length < sizeof(ppp_report_request) || !data)
831 				return B_ERROR;
832 
833 			MutexLocker locker(fLock);
834 			ppp_report_request *request = (ppp_report_request*) data;
835 			// first, we send an initial state report
836 			if (request->type == PPP_CONNECTION_REPORT) {
837 				ppp_report_packet report;
838 				report.type = PPP_CONNECTION_REPORT;
839 				report.code = StateMachine().fLastConnectionReportCode;
840 				report.length = sizeof(fID);
841 				KPPPReportManager::SendReport(request->thread, &report);
842 				if (request->flags & PPP_REMOVE_AFTER_REPORT)
843 					return B_OK;
844 			}
845 			ReportManager().EnableReports(request->type, request->thread,
846 				request->flags);
847 			break;
848 		}
849 
850 		case PPPC_DISABLE_REPORTS:
851 		{
852 			if (length < sizeof(ppp_report_request) || !data)
853 				return B_ERROR;
854 
855 			ppp_report_request *request = (ppp_report_request*) data;
856 			ReportManager().DisableReports(request->type, request->thread);
857 			break;
858 		}
859 
860 		case PPPC_GET_STATISTICS:
861 			if (length < sizeof(ppp_statistics) || !data)
862 				return B_ERROR;
863 
864 			memcpy(data, &fStatistics, sizeof(ppp_statistics));
865 			break;
866 
867 		case PPPC_CONTROL_DEVICE:
868 		{
869 			if (length < sizeof(ppp_control_info) || !data)
870 				return B_ERROR;
871 
872 			ppp_control_info *control = (ppp_control_info*) data;
873 			if (control->index != 0 || !Device())
874 				return B_BAD_INDEX;
875 
876 			return Device()->Control(control->op, control->data, control->length);
877 		}
878 
879 		case PPPC_CONTROL_PROTOCOL:
880 		{
881 			if (length < sizeof(ppp_control_info) || !data)
882 				return B_ERROR;
883 
884 			ppp_control_info *control = (ppp_control_info*) data;
885 			KPPPProtocol *protocol = ProtocolAt(control->index);
886 			if (!protocol)
887 				return B_BAD_INDEX;
888 
889 			return protocol->Control(control->op, control->data, control->length);
890 		}
891 
892 		case PPPC_CONTROL_OPTION_HANDLER:
893 		{
894 			if (length < sizeof(ppp_control_info) || !data)
895 				return B_ERROR;
896 
897 			ppp_control_info *control = (ppp_control_info*) data;
898 			KPPPOptionHandler *optionHandler = LCP().OptionHandlerAt(control->index);
899 			if (!optionHandler)
900 				return B_BAD_INDEX;
901 
902 			return optionHandler->Control(control->op, control->data,
903 				control->length);
904 		}
905 
906 		case PPPC_CONTROL_LCP_EXTENSION:
907 		{
908 			if (length < sizeof(ppp_control_info) || !data)
909 				return B_ERROR;
910 
911 			ppp_control_info *control = (ppp_control_info*) data;
912 			KPPPLCPExtension *lcpExtension = LCP().LCPExtensionAt(control->index);
913 			if (!lcpExtension)
914 				return B_BAD_INDEX;
915 
916 			return lcpExtension->Control(control->op, control->data,
917 				control->length);
918 		}
919 
920 		case PPPC_CONTROL_CHILD:
921 		{
922 			if (length < sizeof(ppp_control_info) || !data)
923 				return B_ERROR;
924 
925 			ppp_control_info *control = (ppp_control_info*) data;
926 			KPPPInterface *child = ChildAt(control->index);
927 			if (!child)
928 				return B_BAD_INDEX;
929 
930 			return child->Control(control->op, control->data, control->length);
931 		}
932 
933 		default:
934 			dprintf("bad ppp_interface_control!\n");
935 			return B_BAD_VALUE;
936 	}
937 
938 	return B_OK;
939 }
940 
941 
942 /*!	\brief Sets a new device for this interface.
943 
944 	A device add-on should call this method to register itself. The best place to do
945 	this is in your module's \c add_to() function.
946 
947 	\param device The device object.
948 
949 	\return \c true if successful or \c false otherwise.
950 
951 	\sa KPPPDevice
952 	\sa kppp_module_info
953 */
954 bool
SetDevice(KPPPDevice * device)955 KPPPInterface::SetDevice(KPPPDevice *device)
956 {
957 	TRACE("KPPPInterface: SetDevice(%p)\n", device);
958 
959 	if (device && &device->Interface() != this)
960 		return false;
961 
962 	if (IsMultilink() && !Parent())
963 		return false;
964 			// main interfaces do not have devices
965 
966 	MutexLocker locker(fLock);
967 
968 	if (Phase() != PPP_DOWN_PHASE)
969 		return false;
970 			// a running connection may not change
971 
972 	if (fDevice && (IsUp() || fDevice->IsUp()))
973 		Down();
974 
975 	fDevice = device;
976 	SetNext(device);
977 
978 	if (fDevice)
979 		fMRU = fDevice->MTU() - 2;
980 
981 	CalculateInterfaceMTU();
982 	CalculateBaudRate();
983 
984 	return true;
985 }
986 
987 
988 /*!	\brief Adds a new protocol to this interface.
989 
990 	NOTE: You can only add protocols in \c PPP_DOWN_PHASE. \n
991 	A protocol add-on should call this method to register itself. The best place to do
992 	this is in your module's \c add_to() function.
993 
994 	\param protocol The protocol object.
995 
996 	\return \c true if successful or \c false otherwise.
997 
998 	\sa KPPPProtocol
999 	\sa kppp_module_info
1000 */
1001 bool
AddProtocol(KPPPProtocol * protocol)1002 KPPPInterface::AddProtocol(KPPPProtocol *protocol)
1003 {
1004 	// Find insert position after the last protocol
1005 	// with the same level.
1006 
1007 	TRACE("KPPPInterface: AddProtocol(%X)\n",
1008 		protocol ? protocol->ProtocolNumber() : 0);
1009 
1010 	if (!protocol || &protocol->Interface() != this
1011 			|| protocol->Level() == PPP_INTERFACE_LEVEL)
1012 		return false;
1013 
1014 	MutexLocker locker(fLock);
1015 
1016 	if (Phase() != PPP_DOWN_PHASE)
1017 		return false;
1018 			// a running connection may not change
1019 
1020 	KPPPProtocol *current = fFirstProtocol, *previous = NULL;
1021 
1022 	while (current) {
1023 		if (current->Level() < protocol->Level())
1024 			break;
1025 
1026 		previous = current;
1027 		current = current->NextProtocol();
1028 	}
1029 
1030 	if (!current) {
1031 		if (!previous)
1032 			fFirstProtocol = protocol;
1033 		else
1034 			previous->SetNextProtocol(protocol);
1035 
1036 		// set up the last protocol in the chain
1037 		protocol->SetNextProtocol(NULL);
1038 			// this also sets next to NULL
1039 		protocol->SetNext(this);
1040 			// we need to set us as the next layer for the last protocol
1041 	} else {
1042 		protocol->SetNextProtocol(current);
1043 
1044 		if (!previous)
1045 			fFirstProtocol = protocol;
1046 		else
1047 			previous->SetNextProtocol(protocol);
1048 	}
1049 
1050 	if (protocol->Level() < PPP_PROTOCOL_LEVEL)
1051 		CalculateInterfaceMTU();
1052 
1053 	if (IsUp() || Phase() >= protocol->ActivationPhase())
1054 		protocol->Up();
1055 
1056 	return true;
1057 }
1058 
1059 
1060 /*!	\brief Removes a protocol from this interface.
1061 
1062 	NOTE: You can only remove protocols in \c PPP_DOWN_PHASE. \n
1063 	A protocol add-on should call this method to remove itself explicitly from the
1064 	interface. \n
1065 	Normally, this method is called in KPPPProtocol's destructor. Do not call it
1066 	yourself unless you know what you do!
1067 
1068 	\param protocol The protocol object.
1069 
1070 	\return \c true if successful or \c false otherwise.
1071 */
1072 bool
RemoveProtocol(KPPPProtocol * protocol)1073 KPPPInterface::RemoveProtocol(KPPPProtocol *protocol)
1074 {
1075 	TRACE("KPPPInterface: RemoveProtocol(%X)\n",
1076 		protocol ? protocol->ProtocolNumber() : 0);
1077 
1078 	MutexLocker locker(fLock);
1079 
1080 	if (Phase() != PPP_DOWN_PHASE)
1081 		return false;
1082 			// a running connection may not change
1083 
1084 	KPPPProtocol *current = fFirstProtocol, *previous = NULL;
1085 
1086 	while (current) {
1087 		if (current == protocol) {
1088 			if (!protocol->IsDown())
1089 				protocol->Down();
1090 
1091 			if (previous) {
1092 				previous->SetNextProtocol(current->NextProtocol());
1093 
1094 				// set us as next layer if needed
1095 				if (!previous->Next())
1096 					previous->SetNext(this);
1097 			} else
1098 				fFirstProtocol = current->NextProtocol();
1099 
1100 			current->SetNextProtocol(NULL);
1101 
1102 			CalculateInterfaceMTU();
1103 
1104 			return true;
1105 		}
1106 
1107 		previous = current;
1108 		current = current->NextProtocol();
1109 	}
1110 
1111 	return false;
1112 }
1113 
1114 
1115 //!	Returns the number of protocol modules belonging to this interface.
1116 int32
CountProtocols() const1117 KPPPInterface::CountProtocols() const
1118 {
1119 	MutexLocker locker(fLock);
1120 
1121 	KPPPProtocol *protocol = FirstProtocol();
1122 
1123 	int32 count = 0;
1124 	for (; protocol; protocol = protocol->NextProtocol())
1125 		++count;
1126 
1127 	return count;
1128 }
1129 
1130 
1131 //!	Returns the protocol at the given \a index or \c NULL if it could not be found.
1132 KPPPProtocol*
ProtocolAt(int32 index) const1133 KPPPInterface::ProtocolAt(int32 index) const
1134 {
1135 	MutexLocker locker(fLock);
1136 
1137 	KPPPProtocol *protocol = FirstProtocol();
1138 
1139 	int32 currentIndex = 0;
1140 	for (; protocol && currentIndex != index; protocol = protocol->NextProtocol())
1141 		++currentIndex;
1142 
1143 	return protocol;
1144 }
1145 
1146 
1147 /*!	\brief Returns the protocol object responsible for a given protocol number.
1148 
1149 	\param protocolNumber The protocol number that the object should handle.
1150 	\param start (Optional): Start with this protocol. Can be used for iteration.
1151 
1152 	\return Either the object that was found or \c NULL.
1153 */
1154 KPPPProtocol*
ProtocolFor(uint16 protocolNumber,KPPPProtocol * start) const1155 KPPPInterface::ProtocolFor(uint16 protocolNumber, KPPPProtocol *start) const
1156 {
1157 	TRACE("KPPPInterface: ProtocolFor(%X)\n", protocolNumber);
1158 
1159 	// MutexLocker locker(fLock);
1160 		// already locked in ::Receive, uncomment this line will cause double lock
1161 
1162 	KPPPProtocol *current = start ? start : FirstProtocol();
1163 
1164 	for (; current; current = current->NextProtocol()) {
1165 		if (current->ProtocolNumber() == protocolNumber
1166 				|| (current->Flags() & PPP_INCLUDES_NCP
1167 					&& (current->ProtocolNumber() & 0x7FFF)
1168 						== (protocolNumber & 0x7FFF)))
1169 			return current;
1170 	}
1171 
1172 	return NULL;
1173 }
1174 
1175 
1176 //!	Adds a new child interface (used for multilink interfaces).
1177 bool
AddChild(KPPPInterface * child)1178 KPPPInterface::AddChild(KPPPInterface *child)
1179 {
1180 	TRACE("KPPPInterface: AddChild(%lX)\n", child ? child->ID() : 0);
1181 
1182 	if (!child)
1183 		return false;
1184 
1185 	MutexLocker locker(fLock);
1186 
1187 	if (fChildren.HasItem(child) || !fChildren.AddItem(child))
1188 		return false;
1189 
1190 	child->SetParent(this);
1191 
1192 	return true;
1193 }
1194 
1195 
1196 //!	Removes a new child from this interface (used for multilink interfaces).
1197 bool
RemoveChild(KPPPInterface * child)1198 KPPPInterface::RemoveChild(KPPPInterface *child)
1199 {
1200 	TRACE("KPPPInterface: RemoveChild(%lX)\n", child ? child->ID() : 0);
1201 
1202 	MutexLocker locker(fLock);
1203 
1204 	if (!fChildren.RemoveItem(child))
1205 		return false;
1206 
1207 	child->SetParent(NULL);
1208 
1209 	// parents cannot exist without their children
1210 	if (CountChildren() == 0 && fManager && Ifnet())
1211 		Delete();
1212 
1213 	return true;
1214 }
1215 
1216 
1217 //!	Returns the child interface at the given \a index (used for multilink interfaces).
1218 KPPPInterface*
ChildAt(int32 index) const1219 KPPPInterface::ChildAt(int32 index) const
1220 {
1221 	TRACE("KPPPInterface: ChildAt(%ld)\n", index);
1222 
1223 	MutexLocker locker(fLock);
1224 
1225 	KPPPInterface *child = fChildren.ItemAt(index);
1226 
1227 	if (child == fChildren.GetDefaultItem())
1228 		return NULL;
1229 
1230 	return child;
1231 }
1232 
1233 
1234 //!	Enables or disables the auto-reconnect feture.
1235 void
SetAutoReconnect(bool autoReconnect)1236 KPPPInterface::SetAutoReconnect(bool autoReconnect)
1237 {
1238 	TRACE("KPPPInterface: SetAutoReconnect(%s)\n", autoReconnect ? "true" : "false");
1239 
1240 	if (Mode() != PPP_CLIENT_MODE)
1241 		return;
1242 
1243 	fAutoReconnect = autoReconnect;
1244 }
1245 
1246 
1247 //!	Enables or disables the connect-on-demand feature.
1248 void
SetConnectOnDemand(bool connectOnDemand)1249 KPPPInterface::SetConnectOnDemand(bool connectOnDemand)
1250 {
1251 	// All protocols must check if ConnectOnDemand was enabled/disabled after this
1252 	// interface went down. This is the only situation where a change is relevant.
1253 
1254 	TRACE("KPPPInterface: SetConnectOnDemand(%s)\n", connectOnDemand ? "true" : "false");
1255 
1256 	MutexLocker locker(fLock);
1257 
1258 	// Only clients support ConnectOnDemand.
1259 	if (Mode() != PPP_CLIENT_MODE) {
1260 		TRACE("KPPPInterface::SetConnectOnDemand(): Wrong mode!\n");
1261 		fConnectOnDemand = false;
1262 		return;
1263 	} else if (DoesConnectOnDemand() == connectOnDemand)
1264 		return;
1265 
1266 	fConnectOnDemand = connectOnDemand;
1267 
1268 	// Do not allow changes when we are disconnected (only main interfaces).
1269 	// This would make no sense because
1270 	// - enabling: this cannot happen because hidden interfaces are deleted if they
1271 	//    could not establish a connection (the user cannot access hidden interfaces)
1272 	// - disabling: the interface disappears as seen from the user, so we delete it
1273 	if (!Parent() && State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) {
1274 		if (!connectOnDemand)
1275 			Delete();
1276 				// as long as the protocols were not configured we can just delete us
1277 
1278 		return;
1279 	}
1280 
1281 	// check if we need to set/unset flags
1282 	if (connectOnDemand) {
1283 		if (Ifnet())
1284 			Ifnet()->flags |= IFF_UP;
1285 	} else if (!connectOnDemand && Phase() < PPP_ESTABLISHED_PHASE) {
1286 		if (Ifnet())
1287 			Ifnet()->flags &= ~IFF_UP;
1288 	}
1289 }
1290 
1291 
1292 //!	Sets whether the user is asked before establishing the connection.
1293 void
SetAskBeforeConnecting(bool ask)1294 KPPPInterface::SetAskBeforeConnecting(bool ask)
1295 {
1296 	MutexLocker locker(fLock);
1297 
1298 	bool old = fAskBeforeConnecting;
1299 	fAskBeforeConnecting = ask;
1300 
1301 	if (old && fAskBeforeConnecting == false && State() == PPP_STARTING_STATE
1302 			&& Phase() == PPP_DOWN_PHASE) {
1303 		// locker.Unlock();
1304 		StateMachine().ContinueOpenEvent();
1305 	}
1306 }
1307 
1308 
1309 //!	Sets Protocol-Field-Compression options.
1310 bool
SetPFCOptions(uint8 pfcOptions)1311 KPPPInterface::SetPFCOptions(uint8 pfcOptions)
1312 {
1313 	TRACE("KPPPInterface: SetPFCOptions(0x%X)\n", pfcOptions);
1314 
1315 	MutexLocker locker(fLock);
1316 
1317 	if (PFCOptions() & PPP_FREEZE_PFC_OPTIONS)
1318 		return false;
1319 
1320 	fPFCOptions = pfcOptions;
1321 	return true;
1322 }
1323 
1324 
1325 /*!	\brief Brings this interface up.
1326 
1327 	\c Down() overrides all \c Up() requests. \n
1328 	This method runs an asynchronous process (it returns immediately).
1329 
1330 	\return \c false on error.
1331 */
1332 bool
Up()1333 KPPPInterface::Up()
1334 {
1335 	TRACE("KPPPInterface: Up()\n");
1336 
1337 	if (InitCheck() != B_OK || Phase() == PPP_TERMINATION_PHASE)
1338 		return false;
1339 
1340 	if (IsUp())
1341 		return true;
1342 
1343 	MutexLocker locker(fLock);
1344 	StateMachine().OpenEvent();
1345 
1346 	return true;
1347 }
1348 
1349 
1350 /*!	\brief Brings this interface down.
1351 
1352 	\c Down() overrides all \c Up() requests. \n
1353 	This method runs an asynchronous process (it returns immediately).
1354 
1355 	\return \c false on error.
1356 */
1357 bool
Down()1358 KPPPInterface::Down()
1359 {
1360 	TRACE("KPPPInterface: Down()\n");
1361 
1362 	if (InitCheck() != B_OK)
1363 		return false;
1364 	else if (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE)
1365 		return true;
1366 
1367 	send_data_with_timeout(fReconnectThread, 0, NULL, 0, 200);
1368 		// tell the reconnect thread to abort its attempt (if it's still waiting)
1369 
1370 	MutexLocker locker(fLock);
1371 	StateMachine().CloseEvent();
1372 
1373 	return true;
1374 }
1375 
1376 
1377 //!	Waits for connection establishment. Returns true if successful.
1378 bool
WaitForConnection()1379 KPPPInterface::WaitForConnection()
1380 {
1381 	TRACE("KPPPInterface: WaitForConnection()\n");
1382 
1383 	if (InitCheck() != B_OK)
1384 		return false;
1385 
1386 	// just delay ~3 seconds to wait for ppp go up
1387 	for (uint32 i = 0; i < 10000; i++)
1388 		for (uint32 j = 0; j < 3000000; j++)
1389 
1390 	return true; // for temporary
1391 
1392 	ReportManager().EnableReports(PPP_CONNECTION_REPORT, find_thread(NULL));
1393 
1394 	ppp_report_packet report;
1395 	thread_id sender;
1396 	bool successful = false;
1397 	while (true) {
1398 		if (receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE)
1399 			continue;
1400 
1401 		if (report.type == PPP_DESTRUCTION_REPORT)
1402 			break;
1403 		else if (report.type != PPP_CONNECTION_REPORT)
1404 			continue;
1405 
1406 		if (report.code == PPP_REPORT_UP_SUCCESSFUL) {
1407 			successful = true;
1408 			break;
1409 		} else if (report.code == PPP_REPORT_DOWN_SUCCESSFUL)
1410 			break;
1411 	}
1412 
1413 	ReportManager().DisableReports(PPP_CONNECTION_REPORT, find_thread(NULL));
1414 	dprintf("KPPPInterface: WaitForConnection():%s\n", successful ? "True" : "False");
1415 	return successful;
1416 }
1417 
1418 
1419 /*!	\brief Loads modules specified in the settings structure.
1420 
1421 	\param settings PPP interface description file format settings.
1422 	\param start Index of driver_parameter to start with.
1423 	\param count Number of driver_parameters to look at.
1424 
1425 	\return \c true if successful or \c false otherwise.
1426 */
1427 bool
LoadModules(driver_settings * settings,int32 start,int32 count)1428 KPPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count)
1429 {
1430 	TRACE("KPPPInterface: LoadModules()\n");
1431 
1432 	if (Phase() != PPP_DOWN_PHASE)
1433 		return false;
1434 			// a running connection may not change
1435 
1436 	ppp_module_key_type type;
1437 		// which type key was used for loading this module?
1438 
1439 	const char *name = NULL;
1440 
1441 	// multilink handling
1442 	for (int32 index = start;
1443 			index < settings->parameter_count && index < (start + count); index++) {
1444 		if (!strcasecmp(settings->parameters[index].name, PPP_MULTILINK_KEY)
1445 				&& settings->parameters[index].value_count > 0) {
1446 			if (!LoadModule(settings->parameters[index].values[0],
1447 					&settings->parameters[index], PPP_MULTILINK_KEY_TYPE))
1448 				return false;
1449 			break;
1450 		}
1451 	}
1452 
1453 	// are we a multilink main interface?
1454 	if (IsMultilink() && !Parent()) {
1455 		// main interfaces only load the multilink module
1456 		// and create a child using their settings
1457 		fManager->CreateInterface(settings, ID());
1458 		return true;
1459 	}
1460 
1461 	for (int32 index = start;
1462 			index < settings->parameter_count && index < start + count; index++) {
1463 		type = PPP_UNDEFINED_KEY_TYPE;
1464 
1465 		name = settings->parameters[index].name;
1466 
1467 		if (!strcasecmp(name, PPP_LOAD_MODULE_KEY))
1468 			type = PPP_LOAD_MODULE_KEY_TYPE;
1469 		else if (!strcasecmp(name, PPP_DEVICE_KEY))
1470 			type = PPP_DEVICE_KEY_TYPE;
1471 		else if (!strcasecmp(name, PPP_PROTOCOL_KEY))
1472 			type = PPP_PROTOCOL_KEY_TYPE;
1473 		else if (!strcasecmp(name, PPP_AUTHENTICATOR_KEY))
1474 			type = PPP_AUTHENTICATOR_KEY_TYPE;
1475 
1476 		if (type >= 0)
1477 			for (int32 value_id = 0; value_id < settings->parameters[index].value_count;
1478 					value_id++)
1479 				if (!LoadModule(settings->parameters[index].values[value_id],
1480 						&settings->parameters[index], type))
1481 					return false;
1482 	}
1483 
1484 	return true;
1485 }
1486 
1487 
1488 /*!	\brief Loads a specific module.
1489 
1490 	\param name Name of the module.
1491 	\param parameter Module settings.
1492 	\param type Type of module.
1493 
1494 	\return \c true if successful or \c false otherwise.
1495 */
1496 bool
LoadModule(const char * name,driver_parameter * parameter,ppp_module_key_type type)1497 KPPPInterface::LoadModule(const char *name, driver_parameter *parameter,
1498 	ppp_module_key_type type)
1499 {
1500 	TRACE("KPPPInterface: LoadModule(%s)\n", name ? name : "XXX: NO NAME");
1501 
1502 	if (Phase() != PPP_DOWN_PHASE)
1503 		return false;
1504 			// a running connection may not change
1505 
1506 	if (!name || strlen(name) > B_FILE_NAME_LENGTH)
1507 		return false;
1508 
1509 	char *moduleName = new char[B_PATH_NAME_LENGTH];
1510 
1511 	sprintf(moduleName, "%s/%s", PPP_MODULES_PATH, name);
1512 
1513 	ppp_module_info *module;
1514 	if (get_module(moduleName, (module_info**) &module) != B_OK) {
1515 		delete[] moduleName;
1516 		return false;
1517 	}
1518 
1519 	// add the module to the list of loaded modules
1520 	// for putting them on our destruction
1521 	fModules.AddItem(moduleName);
1522 
1523 	return module->add_to(Parent() ? *Parent() : *this, this, parameter, type);
1524 }
1525 
1526 
1527 //!	Always returns true.
1528 bool
IsAllowedToSend() const1529 KPPPInterface::IsAllowedToSend() const
1530 {
1531 	return true;
1532 }
1533 
1534 
1535 /*!	\brief Sends a packet to the device.
1536 
1537 	This brings the interface up if connect-on-demand is enabled and we are not
1538 	connected. \n
1539 	PFC encoding is handled here. \n
1540 	NOTE: In order to prevent interface destruction while sending you must either
1541 	hold a refcount for this interface or make sure it is locked.
1542 
1543 	\param packet The packet.
1544 	\param protocolNumber The packet's protocol number.
1545 
1546 	\return
1547 		- \c B_OK: Sending was successful.
1548 		- \c B_ERROR: Some error occured.
1549 */
1550 status_t
Send(net_buffer * packet,uint16 protocolNumber)1551 KPPPInterface::Send(net_buffer *packet, uint16 protocolNumber)
1552 {
1553 	TRACE("KPPPInterface: Send(0x%X)\n", protocolNumber);
1554 
1555 	if (!packet)
1556 		return B_ERROR;
1557 
1558 	// we must pass the basic tests like:
1559 	// do we have a device?
1560 	// did we load all modules?
1561 	if (InitCheck() != B_OK) {
1562 		ERROR("InitCheck() fail\n");
1563 		gBufferModule->free(packet);
1564 		return B_ERROR;
1565 	}
1566 
1567 
1568 	// go up if ConnectOnDemand is enabled and we are disconnected
1569 	// TODO: our new netstack will simplify ConnectOnDemand handling, so
1570 	// we do not have to handle it here
1571 	if ((protocolNumber != PPP_LCP_PROTOCOL && DoesConnectOnDemand()
1572 			&& (Phase() == PPP_DOWN_PHASE
1573 				|| Phase() == PPP_ESTABLISHMENT_PHASE)
1574 			&& !Up()) && !WaitForConnection()) {
1575 		dprintf("DoesConnectOnDemand fail!\n");
1576 		// gBufferModule->free(packet);
1577 		return B_ERROR;
1578 	}
1579 
1580 	// find the protocol handler for the current protocol number
1581 	KPPPProtocol *protocol = ProtocolFor(protocolNumber);
1582 	while (protocol && !protocol->IsEnabled())
1583 		protocol = protocol->NextProtocol() ?
1584 			ProtocolFor(protocolNumber, protocol->NextProtocol()) : NULL;
1585 
1586 #if DEBUG
1587 	if (!protocol)
1588 		TRACE("KPPPInterface::Send(): no protocol found!\n");
1589 	else if (!Device()->IsUp())
1590 		TRACE("KPPPInterface::Send(): device is not up!\n");
1591 	else if (!protocol->IsEnabled())
1592 		TRACE("KPPPInterface::Send(): protocol not enabled!\n");
1593 	else if (!IsProtocolAllowed(*protocol))
1594 		TRACE("KPPPInterface::Send(): protocol not allowed to send!\n");
1595 	else
1596 		TRACE("KPPPInterface::Send(): protocol allowed\n");
1597 #endif
1598 
1599 	// make sure that protocol is allowed to send and everything is up
1600 	if (Device()->IsUp() && protocolNumber == 0x0021) {
1601 			// IP_PROTOCOL 0x0021
1602 		TRACE("send IP packet!\n");
1603 	} else if (!Device()->IsUp() || !protocol || !protocol->IsEnabled()
1604 			|| !IsProtocolAllowed(*protocol)) {
1605 		ERROR("KPPPInterface::Send(): Device is down, throw packet away!!\n");
1606 		// gBufferModule->free(packet);
1607 		return B_ERROR;
1608 	}
1609 
1610 	// encode in ppp frame and consider using PFC
1611 	if (UseLocalPFC() && (protocolNumber & 0xFF00) == 0) {
1612 		TRACE("%s::%s should not go here\n", __FILE__, __func__);
1613 		NetBufferPrepend<uint8> bufferHeader(packet);
1614 		if (bufferHeader.Status() != B_OK)
1615 			return bufferHeader.Status();
1616 
1617 		uint8 &header = bufferHeader.Data();
1618 
1619 		// memcpy(header.destination, ether_pppoe_ppp_header, 1);
1620 		header = (protocolNumber & 0x00FF);
1621 		// bufferHeader.Sync();
1622 
1623 	} else {
1624 		NetBufferPrepend<uint16> bufferHeader(packet);
1625 		if (bufferHeader.Status() != B_OK)
1626 			return bufferHeader.Status();
1627 
1628 		uint16 &header = bufferHeader.Data();
1629 
1630 		// set protocol (the only header field)
1631 		header = htons(protocolNumber);
1632 		// bufferHeader.Sync();
1633 	}
1634 
1635 	// pass to device if we're either not a multilink interface or a child interface
1636 	if (!IsMultilink() || Parent()) {
1637 		// check if packet is too big for device
1638 		uint32 length = packet->size;
1639 
1640 		if (length > MRU()) {
1641 			dprintf("packet too large!\n");
1642 			gBufferModule->free(packet);
1643 			return B_ERROR;
1644 		}
1645 
1646 		atomic_add64(&fStatistics.bytesSent, length);
1647 		atomic_add64(&fStatistics.packetsSent, 1);
1648 		TRACE("%s::%s SendToNext\n", __FILE__, __func__);
1649 		return SendToNext(packet, 0);
1650 			// this is normally the device, but there can be something inbetween
1651 	} else {
1652 		// the multilink protocol should have sent it to some child interface
1653 		TRACE("It is weird to go here!\n");
1654 		gBufferModule->free(packet);
1655 		return B_ERROR;
1656 	}
1657 }
1658 
1659 
1660 /*!	\brief Receives a packet.
1661 
1662 	Encapsulation protocols may use this method to pass encapsulated packets to the
1663 	PPP interface. Packets will be handled as if they were raw packets that came
1664 	directly from the device via \c ReceiveFromDevice(). \n
1665 	If no handler could be found in this interface the parent's \c Receive() method
1666 	is called.
1667 
1668 	\param packet The packet.
1669 	\param protocolNumber The packet's protocol number.
1670 
1671 	\return
1672 		- \c B_OK: Receiving was successful.
1673 		- \c B_ERROR: Some error occured.
1674 		- \c PPP_REJECTED: No protocol handler could be found for this packet.
1675 		- \c PPP_DISCARDED: The protocol handler(s) did not handle this packet.
1676 */
1677 status_t
Receive(net_buffer * packet,uint16 protocolNumber)1678 KPPPInterface::Receive(net_buffer *packet, uint16 protocolNumber)
1679 {
1680 	TRACE("KPPPInterface: Receive(0x%X)\n", protocolNumber);
1681 
1682 	if (!packet)
1683 		return B_ERROR;
1684 
1685 	MutexLocker locker(fLock);
1686 
1687 	int32 result = PPP_REJECTED;
1688 		// assume we have no handler
1689 
1690 	if (protocolNumber == 0x0021 && Device() && Device()->IsUp()) {
1691 			// IP_PROTOCOL 0x0021
1692 		TRACE("%s::%s: receiving IP packet\n", __FILE__, __func__);
1693 		ppp_device* dev=(ppp_device*)Ifnet();
1694 
1695 		if (dev)
1696 			return gStackModule->fifo_enqueue_buffer(&(dev->ppp_fifo), packet);
1697 		else {
1698 			dprintf("%s::%s: no ppp_device\n", __FILE__, __func__);
1699 			return B_ERROR;
1700 		}
1701 	}
1702 	// // Set our interface as the receiver.
1703 	// // The real netstack protocols (IP, IPX, etc.) might get confused if our
1704 	// // interface is a main interface and at the same time not registered
1705 	// // because then there is no receiver interface.
1706 	// // PPP NCPs should be aware of that!
1707 	// if (packet->m_flags & M_PKTHDR && Ifnet() != NULL)
1708 	// 	packet->m_pkthdr.rcvif = Ifnet();
1709 
1710 	// Find handler and let it parse the packet.
1711 	// The handler does need not be up because if we are a server
1712 	// the handler might be upped by this packet.
1713 	// If authenticating we only allow authentication phase protocols.
1714 	KPPPProtocol *protocol = ProtocolFor(protocolNumber);
1715 	for (; protocol;
1716 			protocol = protocol->NextProtocol() ?
1717 				ProtocolFor(protocolNumber, protocol->NextProtocol()) : NULL) {
1718 		TRACE("KPPPInterface::Receive(): trying protocol\n");
1719 
1720 		if (!protocol->IsEnabled() || !IsProtocolAllowed(*protocol))
1721 			continue;
1722 				// skip handler if disabled or not allowed
1723 
1724 		result = protocol->Receive(packet, protocolNumber);
1725 		if (result == PPP_UNHANDLED)
1726 			continue;
1727 
1728 		return result;
1729 	}
1730 
1731 	TRACE("KPPPInterface::Receive(): trying parent\n");
1732 
1733 	// maybe the parent interface can handle the packet
1734 	if (Parent())
1735 		return Parent()->Receive(packet, protocolNumber);
1736 
1737 	if (result == PPP_UNHANDLED) {
1738 		gBufferModule->free(packet);
1739 		return PPP_DISCARDED;
1740 	} else {
1741 		StateMachine().RUCEvent(packet, protocolNumber);
1742 		return PPP_REJECTED;
1743 	}
1744 }
1745 
1746 
1747 /*!	\brief Receives a base PPP packet from the device.
1748 
1749 	KPPPDevice should call this method when it receives a packet. \n
1750 	PFC decoding is handled here.
1751 
1752 	\param packet The packet.
1753 
1754 	\return
1755 		- \c B_OK: Receiving was successful.
1756 		- \c B_ERROR: Some error occured.
1757 		- \c PPP_REJECTED: No protocol handler could be found for this packet.
1758 		- \c PPP_DISCARDED: The protocol handler(s) did not handle this packet.
1759 */
1760 status_t
ReceiveFromDevice(net_buffer * packet)1761 KPPPInterface::ReceiveFromDevice(net_buffer *packet)
1762 {
1763 	TRACE("KPPPInterface: ReceiveFromDevice()\n");
1764 
1765 	if (!packet)
1766 		return B_ERROR;
1767 
1768 	if (InitCheck() != B_OK) {
1769 		gBufferModule->free(packet);
1770 		return B_ERROR;
1771 	}
1772 
1773 	uint32 length = packet->size;
1774 	// decode ppp frame and recognize PFC
1775 	NetBufferHeaderReader<uint16> bufferHeader(packet);
1776 	if (bufferHeader.Status() < B_OK)
1777 		return bufferHeader.Status();
1778 
1779 	uint16 &header = bufferHeader.Data();
1780 	uint16 protocolNumber = ntohs(header); // copy the protocol number
1781 	TRACE("%s::%s: ppp protocol number:%x\n", __FILE__, __func__, protocolNumber);
1782 
1783 	bufferHeader.Remove();
1784 	bufferHeader.Sync();
1785 
1786 	// PFC only use 1 byte for protocol, the next byte is in first byte of message
1787 	if (protocolNumber & (1UL<<8)) {
1788 		NetBufferPrepend<uint8> bufferprepend(packet);
1789 		if (bufferprepend.Status() < B_OK) {
1790 			gBufferModule->free(packet);
1791 			return bufferprepend.Status();
1792 		}
1793 
1794 		uint8 &prepend = bufferprepend.Data();
1795 		prepend = (uint8)(protocolNumber & 0x00FF);
1796 		// bufferprepend.Sync();
1797 		TRACE("%s::%s:PFC protocol:%x\n", __FILE__, __func__, protocolNumber>>8);
1798 	} else {
1799 		TRACE("%s::%s:Non-PFC protocol:%x\n", __FILE__, __func__, protocolNumber);
1800 	}
1801 
1802 	atomic_add64(&fStatistics.bytesReceived, length);
1803 	atomic_add64(&fStatistics.packetsReceived, 1);
1804 	return Receive(packet, protocolNumber);
1805 }
1806 
1807 
1808 //!	Manages Pulse() calls for all add-ons and hanldes idle-disconnection.
1809 void
Pulse()1810 KPPPInterface::Pulse()
1811 {
1812 	MutexLocker locker(fLock);
1813 
1814 	if (Device())
1815 		Device()->Pulse();
1816 
1817 	KPPPProtocol *protocol = FirstProtocol();
1818 	for (; protocol; protocol = protocol->NextProtocol())
1819 		protocol->Pulse();
1820 
1821 	uint32 currentTime = real_time_clock();
1822 	if (fUpdateIdleSince) {
1823 		fIdleSince = currentTime;
1824 		fUpdateIdleSince = false;
1825 	}
1826 
1827 	// check our idle time and disconnect if needed
1828 	if (fDisconnectAfterIdleSince > 0 && fIdleSince != 0
1829 			&& fIdleSince - currentTime >= fDisconnectAfterIdleSince)
1830 		StateMachine().CloseEvent();
1831 }
1832 
1833 
1834 //!	Registers an ifnet structure for this interface.
1835 bool
RegisterInterface()1836 KPPPInterface::RegisterInterface()
1837 {
1838 	TRACE("KPPPInterface: RegisterInterface()\n");
1839 
1840 	if (fIfnet)
1841 		return true;
1842 			// we are already registered
1843 
1844 	MutexLocker locker(fLock);
1845 
1846 	// only MainInterfaces get an ifnet
1847 	if (IsMultilink() && Parent() && Parent()->RegisterInterface())
1848 		return true;
1849 
1850 	if (!fManager)
1851 		return false;
1852 
1853 	fIfnet = fManager->RegisterInterface(ID());
1854 
1855 	if (!fIfnet) {
1856 		dprintf("%s:%s: damn it no fIfnet device\n", __FILE__, __func__);
1857 		return false;
1858 	}
1859 
1860 	if (DoesConnectOnDemand())
1861 		fIfnet->flags |= IFF_UP;
1862 
1863 	CalculateInterfaceMTU();
1864 	CalculateBaudRate();
1865 
1866 	return true;
1867 }
1868 
1869 
1870 //!	Unregisters this interface's ifnet structure.
1871 bool
UnregisterInterface()1872 KPPPInterface::UnregisterInterface()
1873 {
1874 	TRACE("KPPPInterface: UnregisterInterface()\n");
1875 
1876 	if (!fIfnet)
1877 		return true;
1878 			// we are already unregistered
1879 
1880 	MutexLocker locker(fLock);
1881 
1882 	// only MainInterfaces get an ifnet
1883 	if (IsMultilink() && Parent())
1884 		return true;
1885 
1886 	if (!fManager)
1887 		return false;
1888 
1889 	fManager->UnregisterInterface(ID());
1890 		// this will delete fIfnet, so do not access it anymore!
1891 	fIfnet = NULL;
1892 
1893 	return true;
1894 }
1895 
1896 
1897 //!	Called by KPPPManager: manager routes stack ioctls to the corresponding interface.
1898 status_t
StackControl(uint32 op,void * data)1899 KPPPInterface::StackControl(uint32 op, void *data)
1900 {
1901 	TRACE("KPPPInterface: StackControl(0x%lX)\n", op);
1902 
1903 	switch (op) {
1904 		default:
1905 			return StackControlEachHandler(op, data);
1906 	}
1907 
1908 	return B_OK;
1909 }
1910 
1911 
1912 //!	Utility class used by ControlEachHandler().
1913 template<class T>
1914 class CallStackControl {
1915 	public:
CallStackControl(uint32 op,void * data,status_t & result)1916 		inline CallStackControl(uint32 op, void *data, status_t& result)
1917 			: fOp(op), fData(data), fResult(result) {}
operator ()(T * item)1918 		inline void operator() (T *item)
1919 			{
1920 				if (!item || !item->IsEnabled())
1921 					return;
1922 				status_t tmp = item->StackControl(fOp, fData);
1923 				if (tmp == B_OK && fResult == B_BAD_VALUE)
1924 					fResult = B_OK;
1925 				else if (tmp != B_BAD_VALUE)
1926 					fResult = tmp;
1927 			}
1928 	private:
1929 		uint32 fOp;
1930 		void *fData;
1931 		status_t& fResult;
1932 };
1933 
1934 /*!	\brief This calls Control() with the given parameters for each add-on.
1935 
1936 	\return
1937 		- \c B_OK: All handlers returned B_OK.
1938 		- \c B_BAD_VALUE: No handler was found.
1939 		- Any other value: Error code which was returned by the last failing handler.
1940 */
1941 status_t
StackControlEachHandler(uint32 op,void * data)1942 KPPPInterface::StackControlEachHandler(uint32 op, void *data)
1943 {
1944 	TRACE("KPPPInterface: StackControlEachHandler(0x%lX)\n", op);
1945 
1946 	status_t result = B_BAD_VALUE, tmp;
1947 
1948 	MutexLocker locker(fLock);
1949 
1950 	KPPPProtocol *protocol = FirstProtocol();
1951 	for (; protocol; protocol = protocol->NextProtocol()) {
1952 		tmp = protocol->StackControl(op, data);
1953 		if (tmp == B_OK && result == B_BAD_VALUE)
1954 			result = B_OK;
1955 		else if (tmp != B_BAD_VALUE)
1956 			result = tmp;
1957 	}
1958 
1959 	ForEachItem(LCP().fLCPExtensions,
1960 		CallStackControl<KPPPLCPExtension>(op, data, result));
1961 	ForEachItem(LCP().fOptionHandlers,
1962 		CallStackControl<KPPPOptionHandler>(op, data, result));
1963 
1964 	return result;
1965 }
1966 
1967 
1968 //!	Recalculates the MTU from the MRU (includes encapsulation protocol overheads).
1969 void
CalculateInterfaceMTU()1970 KPPPInterface::CalculateInterfaceMTU()
1971 {
1972 	TRACE("KPPPInterface: CalculateInterfaceMTU()\n");
1973 
1974 	// MutexLocker locker(fLock);
1975 		// uncomment this line will cause double lock
1976 		// alreay locked in ::KPPPInterface
1977 
1978 	fInterfaceMTU = fMRU;
1979 	fHeaderLength = 2;
1980 
1981 	// sum all headers (the protocol field is not counted)
1982 	KPPPProtocol *protocol = FirstProtocol();
1983 	for (; protocol; protocol = protocol->NextProtocol()) {
1984 		if (protocol->Level() < PPP_PROTOCOL_LEVEL)
1985 			fHeaderLength += protocol->Overhead();
1986 	}
1987 
1988 	fInterfaceMTU -= fHeaderLength;
1989 
1990 	if (Ifnet()) {
1991 		Ifnet()->mtu = fInterfaceMTU;
1992 		Ifnet()->header_length = fHeaderLength;
1993 		return;
1994 	}
1995 
1996 	if (Parent())
1997 		Parent()->CalculateInterfaceMTU();
1998 }
1999 
2000 
2001 //!	Recalculates the baud rate.
2002 void
CalculateBaudRate()2003 KPPPInterface::CalculateBaudRate()
2004 {
2005 	TRACE("KPPPInterface: CalculateBaudRate()\n");
2006 
2007 	// MutexLocker locker(fLock); // uncomment this will cause double lock
2008 
2009 	if (!Ifnet())
2010 		return;
2011 
2012 	if (Device())
2013 		fIfnet->link_speed = max_c(Device()->InputTransferRate(),
2014 		Device()->OutputTransferRate());
2015 	else {
2016 		fIfnet->link_speed = 0;
2017 		for (int32 index = 0; index < CountChildren(); index++) {
2018 			if (ChildAt(index)->Ifnet()) {
2019 				fIfnet->link_speed = ChildAt(index)->Ifnet()->link_speed;
2020 				return;
2021 			}
2022 		}
2023 	}
2024 }
2025 
2026 
2027 //!	Reconnects. Waits a given delay (in miliseconds) before reconnecting.
2028 void
Reconnect(uint32 delay)2029 KPPPInterface::Reconnect(uint32 delay)
2030 {
2031 	TRACE("KPPPInterface: Reconnect(%ld)\n", delay);
2032 
2033 	MutexLocker locker(fLock);
2034 
2035 	if (fReconnectThread != -1)
2036 		return;
2037 
2038 	++fConnectAttempt;
2039 
2040 	// start a new thread that calls our Up() method
2041 	reconnect_info info;
2042 	info.interface = this;
2043 	info.thread = &fReconnectThread;
2044 	info.delay = delay;
2045 
2046 	fReconnectThread = spawn_kernel_thread(reconnect_thread,
2047 		"KPPPInterface: reconnect_thread", B_NORMAL_PRIORITY, NULL);
2048 
2049 	resume_thread(fReconnectThread);
2050 
2051 	send_data(fReconnectThread, 0, &info, sizeof(reconnect_info));
2052 }
2053 
2054 
2055 status_t
reconnect_thread(void * data)2056 reconnect_thread(void *data)
2057 {
2058 	reconnect_info info;
2059 	thread_id sender;
2060 	int32 code;
2061 
2062 	receive_data(&sender, &info, sizeof(reconnect_info));
2063 
2064 	// we try to receive data instead of snooze, so we can quit on destruction
2065 	if (receive_data_with_timeout(&sender, &code, NULL, 0, info.delay) == B_OK) {
2066 		*info.thread = -1;
2067 		return B_OK;
2068 	}
2069 
2070 	info.interface->Up();
2071 	*info.thread = -1;
2072 
2073 	return B_OK;
2074 }
2075