xref: /haiku/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp (revision 5e7964b0a929555415798dea3373db9ac4611caa)
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 				{
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
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
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
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
1117 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*
1133 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*
1155 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
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
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*
1219 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
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
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
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
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
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
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
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
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
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
1529 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
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
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
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
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
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
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
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:
1916 		inline CallStackControl(uint32 op, void *data, status_t& result)
1917 			: fOp(op), fData(data), fResult(result) {}
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
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
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
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 //!	Reconnects. Waits a given delay (in miliseconds) before reconnecting.
2026 void
2027 KPPPInterface::Reconnect(uint32 delay)
2028 {
2029 	TRACE("KPPPInterface: Reconnect(%ld)\n", delay);
2030 
2031 	MutexLocker locker(fLock);
2032 
2033 	if (fReconnectThread != -1)
2034 		return;
2035 
2036 	++fConnectAttempt;
2037 
2038 	// start a new thread that calls our Up() method
2039 	reconnect_info info;
2040 	info.interface = this;
2041 	info.thread = &fReconnectThread;
2042 	info.delay = delay;
2043 
2044 	fReconnectThread = spawn_kernel_thread(reconnect_thread,
2045 		"KPPPInterface: reconnect_thread", B_NORMAL_PRIORITY, NULL);
2046 
2047 	resume_thread(fReconnectThread);
2048 
2049 	send_data(fReconnectThread, 0, &info, sizeof(reconnect_info));
2050 }
2051 
2052 
2053 status_t
2054 reconnect_thread(void *data)
2055 {
2056 	reconnect_info info;
2057 	thread_id sender;
2058 	int32 code;
2059 
2060 	receive_data(&sender, &info, sizeof(reconnect_info));
2061 
2062 	// we try to receive data instead of snooze, so we can quit on destruction
2063 	if (receive_data_with_timeout(&sender, &code, NULL, 0, info.delay) == B_OK) {
2064 		*info.thread = -1;
2065 		return B_OK;
2066 	}
2067 
2068 	info.interface->Up();
2069 	*info.thread = -1;
2070 
2071 	return B_OK;
2072 }
2073