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