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