1e3724c38Smshlyn/*
285a56a9dSAlexander von Gluck IV * Copyright 2006-2017, Haiku, Inc. All Rights Reserved.
3e3724c38Smshlyn * Distributed under the terms of the MIT License.
4e3724c38Smshlyn *
5e3724c38Smshlyn * Authors:
6e3724c38Smshlyn *		Axel D��rfler, axeld@pinc-software.de
7e3724c38Smshlyn *		Lin Longzhou, linlongzhou@163.com
885a56a9dSAlexander von Gluck IV *		Alexander von Gluck IV, kallisti5@unixzen.com
9e3724c38Smshlyn */
10e3724c38Smshlyn
11e3724c38Smshlyn#include <net_stack.h>
12e3724c38Smshlyn#include <NetBufferUtilities.h>
13e3724c38Smshlyn
14e3724c38Smshlyn#include <KernelExport.h>
15e3724c38Smshlyn
16e3724c38Smshlyn#include <lock.h>
17e3724c38Smshlyn#include <util/AutoLock.h>
18e3724c38Smshlyn#include <util/DoublyLinkedList.h>
19e3724c38Smshlyn
20e3724c38Smshlyn#include <new>
21e3724c38Smshlyn
22e3724c38Smshlyn#include <ppp_device.h>
23e3724c38Smshlyn#include <KPPPManager.h>
24e3724c38Smshlyn
25e3724c38Smshlyn
26e3724c38Smshlynstruct entry_private : ppp_interface_entry, DoublyLinkedListLinkImpl<entry_private> {
27e3724c38Smshlyn};
28e3724c38Smshlyn
29e3724c38Smshlynstatic DoublyLinkedList<entry_private> sEntryList;
30e3724c38Smshlyn
31e3724c38Smshlynnet_buffer_module_info* gBufferModule = NULL;
32e3724c38Smshlynnet_stack_module_info* gStackModule = NULL;
33e3724c38Smshlyn// static struct net_interface* sinterface;
34e3724c38Smshlynstatic mutex sListLock;
35e3724c38Smshlynstatic uint32 ppp_interface_count;
36e3724c38Smshlyn
37e3724c38Smshlyn
38e3724c38Smshlyn//	#pragma mark -
3985a56a9dSAlexander von Gluck IVstatic KPPPInterface* GetInterface(ppp_interface_id ID);
40e3724c38Smshlyn
41e3724c38Smshlynstatic ppp_interface_id
4285a56a9dSAlexander von Gluck IVCreateInterface(const driver_settings* settings, ppp_interface_id parentID)
43e3724c38Smshlyn{
44e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
45e3724c38Smshlyn
46e3724c38Smshlyn	if (parentID > 0) {
47e3724c38Smshlyn		TRACE("Not support Multi_Link yet!\n");
48e3724c38Smshlyn		return 0l;
49e3724c38Smshlyn	}
50e3724c38Smshlyn
51e3724c38Smshlyn	if (settings == NULL) {
52e3724c38Smshlyn		TRACE("No driver_settings yet!\n");
53e3724c38Smshlyn		return 0l;
54e3724c38Smshlyn	}
55e3724c38Smshlyn
56e3724c38Smshlyn	ppp_interface_count++;
5785a56a9dSAlexander von Gluck IV	if (GetInterface(ppp_interface_count) != NULL) {
5885a56a9dSAlexander von Gluck IV		TRACE("PPP Interface already exists!\n");
59e3724c38Smshlyn		return 0l;
6085a56a9dSAlexander von Gluck IV	}
61e3724c38Smshlyn
62e3724c38Smshlyn	entry_private* pentry = new (std::nothrow) entry_private;
63e3724c38Smshlyn	memset(pentry, 0, sizeof(entry_private));
64e3724c38Smshlyn	pentry->accessing = ppp_interface_count;
65e3724c38Smshlyn	sEntryList.Add(pentry);
66e3724c38Smshlyn
6785a56a9dSAlexander von Gluck IV	KPPPInterface* device = new (std::nothrow) KPPPInterface(NULL,
68e3724c38Smshlyn		pentry, ppp_interface_count, NULL, NULL);
69e3724c38Smshlyn
70e3724c38Smshlyn	if (device == NULL || pentry == NULL) {
71e3724c38Smshlyn		TRACE("device or pentry is NULL\n");
72e3724c38Smshlyn		ppp_interface_count--;
73e3724c38Smshlyn		return 0l;
74e3724c38Smshlyn	}
75e3724c38Smshlyn
76162bb429SAlexander von Gluck IV	TRACE("setting ppp_interface_count %" B_PRIu32 "\n", ppp_interface_count);
77e3724c38Smshlyn
78e3724c38Smshlyn	return ppp_interface_count; // only support 1 ppp connection right now
79e3724c38Smshlyn}
80e3724c38Smshlyn
81e3724c38Smshlyn
82e3724c38Smshlynstatic ppp_interface_id
8385a56a9dSAlexander von Gluck IVCreateInterfaceWithName(const char* name, ppp_interface_id parentID)
84e3724c38Smshlyn{
85e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
86e3724c38Smshlyn
87e3724c38Smshlyn	if (parentID > 0) {
88e3724c38Smshlyn		dprintf("Not support Multi_Link yet!\n");
89e3724c38Smshlyn		return(0);
90e3724c38Smshlyn	}
91e3724c38Smshlyn
92e3724c38Smshlyn	if (strncmp(name, "ppp", 3)) {
93e3724c38Smshlyn		dprintf("%s is not ppp device!\n", name);
94e3724c38Smshlyn		return(0);
95e3724c38Smshlyn	}
96e3724c38Smshlyn
97e3724c38Smshlyn	ppp_interface_count++;
98e3724c38Smshlyn	if (GetInterface(ppp_interface_count) != NULL) {
9985a56a9dSAlexander von Gluck IV		TRACE("PPP Interface already exists!\n");
100e3724c38Smshlyn		return 0l;
101e3724c38Smshlyn	}
102e3724c38Smshlyn
103e3724c38Smshlyn	entry_private* pentry = new (std::nothrow) entry_private;
104e3724c38Smshlyn	memset(pentry, 0, sizeof(entry_private));
105e3724c38Smshlyn	pentry->accessing = ppp_interface_count;
106e3724c38Smshlyn	sEntryList.Add(pentry);
107e3724c38Smshlyn
108e3724c38Smshlyn	KPPPInterface* device = new (std::nothrow) KPPPInterface(name,
109e3724c38Smshlyn		pentry, ppp_interface_count, NULL, NULL);
110e3724c38Smshlyn
111e3724c38Smshlyn
112e3724c38Smshlyn	if (device == NULL || pentry == NULL) {
113e3724c38Smshlyn		TRACE("can not create ppp interface!\n");
114e3724c38Smshlyn		ppp_interface_count--;
115e3724c38Smshlyn		return 0l;
116e3724c38Smshlyn	}
117e3724c38Smshlyn
118162bb429SAlexander von Gluck IV	TRACE("setting ppp_interface_count %" B_PRIu32 "\n", ppp_interface_count);
119e3724c38Smshlyn
120e3724c38Smshlyn	return ppp_interface_count;
121e3724c38Smshlyn}
122e3724c38Smshlyn
123e3724c38Smshlyn
124e3724c38Smshlynstatic bool
125e3724c38SmshlynDeleteInterface(ppp_interface_id ID)
126e3724c38Smshlyn{
127e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
128e3724c38Smshlyn
129e3724c38Smshlyn	DoublyLinkedList<entry_private>::Iterator iterator
130e3724c38Smshlyn		= sEntryList.GetIterator();
131e3724c38Smshlyn	while (iterator.HasNext()) {
132e3724c38Smshlyn		entry_private* pentry = iterator.Next();
133e3724c38Smshlyn		if ((ppp_interface_id)pentry->accessing == ID) {
134e3724c38Smshlyn			pentry->deleting = true;
135e3724c38Smshlyn			return true;
136e3724c38Smshlyn		}
137e3724c38Smshlyn	}
138e3724c38Smshlyn
139e3724c38Smshlyn	return false;
140e3724c38Smshlyn}
141e3724c38Smshlyn
142e3724c38Smshlyn
143e3724c38Smshlynstatic bool
144e3724c38SmshlynRemoveInterface(ppp_interface_id ID)
145e3724c38Smshlyn{
146e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
147e3724c38Smshlyn	if (ID <= 0 || ID > ppp_interface_count)
148e3724c38Smshlyn		return false;
149e3724c38Smshlyn
150e3724c38Smshlyn	DoublyLinkedList<entry_private>::Iterator iterator
151e3724c38Smshlyn		= sEntryList.GetIterator();
152e3724c38Smshlyn	while (iterator.HasNext()) {
153e3724c38Smshlyn		entry_private* pentry = iterator.Next();
154e3724c38Smshlyn		if ((ppp_interface_id)pentry->accessing == ID) {
155e3724c38Smshlyn			pentry->deleting = true;
156e3724c38Smshlyn			break;
157e3724c38Smshlyn		}
158e3724c38Smshlyn	}
159e3724c38Smshlyn
160e3724c38Smshlyn	return false;
161e3724c38Smshlyn}
162e3724c38Smshlyn
163e3724c38Smshlyn
16485a56a9dSAlexander von Gluck IVstatic net_device*
165e3724c38SmshlynRegisterInterface(ppp_interface_id ID)
166e3724c38Smshlyn{
167e3724c38Smshlyn	// MutexLocker _(sListLock); // auto_lock
168e3724c38Smshlyn
169e3724c38Smshlyn	entry_private* entry = NULL;
170e3724c38Smshlyn
171e3724c38Smshlyn	DoublyLinkedList<entry_private>::Iterator iterator
172e3724c38Smshlyn		= sEntryList.GetIterator();
173e3724c38Smshlyn	while (iterator.HasNext()) {
174e3724c38Smshlyn		entry_private* pentry = iterator.Next();
175e3724c38Smshlyn		if ((ppp_interface_id)pentry->accessing == ID) {
176e3724c38Smshlyn			entry = pentry;
177e3724c38Smshlyn			break;
178e3724c38Smshlyn		}
179e3724c38Smshlyn	}
180e3724c38Smshlyn
181e3724c38Smshlyn	if (entry == NULL)
182e3724c38Smshlyn		return NULL;
183e3724c38Smshlyn
18485a56a9dSAlexander von Gluck IV	ppp_device* device = new (std::nothrow) ppp_device;
185e3724c38Smshlyn	if (device == NULL)
186e3724c38Smshlyn		return NULL;
187e3724c38Smshlyn
188e3724c38Smshlyn	memset(device, 0, sizeof(ppp_device));
189e3724c38Smshlyn	device->KPPP_Interface = entry->interface;
190e3724c38Smshlyn
191e3724c38Smshlyn	return device;
192e3724c38Smshlyn}
193e3724c38Smshlyn
194e3724c38Smshlyn
19585a56a9dSAlexander von Gluck IVstatic KPPPInterface*
196e3724c38SmshlynGetInterface(ppp_interface_id ID)
197e3724c38Smshlyn{
198e3724c38Smshlyn	// MutexLocker _(sListLock); // auto_lock
199e3724c38Smshlyn
200e3724c38Smshlyn	DoublyLinkedList<entry_private>::Iterator iterator
201e3724c38Smshlyn		= sEntryList.GetIterator();
202e3724c38Smshlyn	while (iterator.HasNext()) {
203e3724c38Smshlyn		entry_private* pentry = iterator.Next();
204162bb429SAlexander von Gluck IV		TRACE("testing interface id:%" B_PRId32 "\n", pentry->accessing);
205e3724c38Smshlyn		if ((ppp_interface_id)(pentry->accessing) == ID) {
206162bb429SAlexander von Gluck IV			TRACE("get interface id:%" B_PRId32 "\n", ID);
207e3724c38Smshlyn			return pentry->interface;
208e3724c38Smshlyn		}
209e3724c38Smshlyn	}
210e3724c38Smshlyn
211162bb429SAlexander von Gluck IV	TRACE("can not get interface id:%" B_PRId32 "\n", ID);
212e3724c38Smshlyn
213e3724c38Smshlyn	return NULL;
214e3724c38Smshlyn}
215e3724c38Smshlyn
216e3724c38Smshlyn
217e3724c38Smshlynstatic bool
218e3724c38SmshlynUnregisterInterface(ppp_interface_id ID)
219e3724c38Smshlyn{
220e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
221e3724c38Smshlyn
222e3724c38Smshlyn	if (ID <= 0 || ID > ppp_interface_count)
223e3724c38Smshlyn		return false;
224e3724c38Smshlyn	return true;
225e3724c38Smshlyn}
226e3724c38Smshlyn
227e3724c38Smshlyn
228e3724c38Smshlynstatic status_t
22985a56a9dSAlexander von Gluck IVControlInterface(ppp_interface_id ID, uint32 op, void* data, size_t length)
230e3724c38Smshlyn{
231e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
232e3724c38Smshlyn
233e3724c38Smshlyn	if (ID <= 0 || ID > ppp_interface_count)
234e3724c38Smshlyn		return B_ERROR;
235e3724c38Smshlyn
236e3724c38Smshlyn	DoublyLinkedList<entry_private>::Iterator iterator
237e3724c38Smshlyn		= sEntryList.GetIterator();
238e3724c38Smshlyn	while (iterator.HasNext()) {
239e3724c38Smshlyn		entry_private* pentry = iterator.Next();
240e3724c38Smshlyn		if ((ppp_interface_id)pentry->accessing == ID)
241e3724c38Smshlyn			return B_OK;
242e3724c38Smshlyn	}
243e3724c38Smshlyn
244e3724c38Smshlyn	return B_ERROR;
245e3724c38Smshlyn}
246e3724c38Smshlyn
247e3724c38Smshlyn
248e3724c38Smshlynstatic int32
24985a56a9dSAlexander von Gluck IVGetInterfaces(ppp_interface_id* interfaces, int32 count, ppp_interface_filter filter)
250e3724c38Smshlyn{
251e3724c38Smshlyn	MutexLocker _(sListLock);
252e3724c38Smshlyn
253e3724c38Smshlyn	if (count <= 0 || count > (int32)ppp_interface_count)
254e3724c38Smshlyn		return(0);
255e3724c38Smshlyn
256e3724c38Smshlyn	uint32 ppp_count = 0;
257e3724c38Smshlyn
258e3724c38Smshlyn	DoublyLinkedList<entry_private>::Iterator iterator
259e3724c38Smshlyn		= sEntryList.GetIterator();
260e3724c38Smshlyn	while (iterator.HasNext()) {
261e3724c38Smshlyn		entry_private* pentry = iterator.Next();
262e3724c38Smshlyn		interfaces[ppp_count] = pentry->accessing;
263e3724c38Smshlyn		ppp_count++;
264e3724c38Smshlyn	}
265e3724c38Smshlyn
266e3724c38Smshlyn	return ppp_count;
267e3724c38Smshlyn}
268e3724c38Smshlyn
269e3724c38Smshlyn
270e3724c38Smshlynstatic int32
271e3724c38SmshlynCountInterfaces(ppp_interface_filter filter)
272e3724c38Smshlyn{
273e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
274e3724c38Smshlyn
275e3724c38Smshlyn	uint32 ppp_count = 0;
276e3724c38Smshlyn
277e3724c38Smshlyn	DoublyLinkedList<entry_private>::Iterator iterator
278e3724c38Smshlyn		= sEntryList.GetIterator();
279e3724c38Smshlyn	while (iterator.HasNext()) {
280e3724c38Smshlyn		iterator.Next();
281e3724c38Smshlyn		ppp_count++;
282e3724c38Smshlyn	}
283e3724c38Smshlyn
284e3724c38Smshlyn	return ppp_count;
285e3724c38Smshlyn}
286e3724c38Smshlyn
287e3724c38Smshlyn
288e3724c38Smshlynstatic void
289e3724c38SmshlynEnableReports(ppp_report_type type, thread_id thread, int32 flags)
290e3724c38Smshlyn{
291e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
292e3724c38Smshlyn
293e3724c38Smshlyn	return; // need more portrait
294e3724c38Smshlyn}
295e3724c38Smshlyn
296e3724c38Smshlyn
297e3724c38Smshlynstatic void
298e3724c38SmshlynDisableReports(ppp_report_type type, thread_id thread)
299e3724c38Smshlyn{
300e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
301e3724c38Smshlyn
302e3724c38Smshlyn	return; // need more portrait
303e3724c38Smshlyn}
304e3724c38Smshlyn
305e3724c38Smshlyn
306e3724c38Smshlynstatic bool
307e3724c38SmshlynDoesReport(ppp_report_type type, thread_id thread)
308e3724c38Smshlyn{
309e3724c38Smshlyn	MutexLocker _(sListLock); // auto_lock
310e3724c38Smshlyn
311e3724c38Smshlyn	return false; // need more portrait
312e3724c38Smshlyn}
313e3724c38Smshlyn
314e3724c38Smshlyn
315e3724c38Smshlynstatic status_t
316e3724c38SmshlynKPPPManager_std_ops(int32 op, ...)
317e3724c38Smshlyn{
318e3724c38Smshlyn	switch (op) {
319e3724c38Smshlyn		case B_MODULE_INIT:
320e3724c38Smshlyn			mutex_init(&sListLock, "KPPPManager");
321e3724c38Smshlyn			new (&sEntryList) DoublyLinkedList<entry_private>;
322e3724c38Smshlyn				// static C++ objects are not initialized in the module startup
323e3724c38Smshlyn			ppp_interface_count = 0;
324e3724c38Smshlyn
325e3724c38Smshlyn			if (get_module(NET_STACK_MODULE_NAME, (module_info**)&gStackModule)
326e3724c38Smshlyn				!= B_OK)
327e3724c38Smshlyn				return B_ERROR;
328e3724c38Smshlyn
329e3724c38Smshlyn			if (get_module(NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule)
330e3724c38Smshlyn				!= B_OK) {
331e3724c38Smshlyn				put_module(NET_STACK_MODULE_NAME);
332e3724c38Smshlyn				return B_ERROR;
333e3724c38Smshlyn			}
334e3724c38Smshlyn
335e3724c38Smshlyn			return B_OK;
336e3724c38Smshlyn
337e3724c38Smshlyn		case B_MODULE_UNINIT:
338e3724c38Smshlyn			mutex_destroy(&sListLock);
339e3724c38Smshlyn
340e3724c38Smshlyn			put_module(NET_BUFFER_MODULE_NAME);
341e3724c38Smshlyn			put_module(NET_STACK_MODULE_NAME);
342e3724c38Smshlyn			return B_OK;
343e3724c38Smshlyn
344e3724c38Smshlyn		default:
345e3724c38Smshlyn			return B_ERROR;
346e3724c38Smshlyn	}
347e3724c38Smshlyn}
348e3724c38Smshlyn
349e3724c38Smshlyn
350e3724c38Smshlynstatic ppp_interface_module_info sKPPPManagerModule = {
351e3724c38Smshlyn	{
352e3724c38Smshlyn		PPP_INTERFACE_MODULE_NAME,
353e3724c38Smshlyn		0,
354e3724c38Smshlyn		KPPPManager_std_ops
355e3724c38Smshlyn	},
356e3724c38Smshlyn	CreateInterface,
357e3724c38Smshlyn	CreateInterfaceWithName,
358e3724c38Smshlyn	DeleteInterface,
359e3724c38Smshlyn	RemoveInterface,
360e3724c38Smshlyn	RegisterInterface,
361e3724c38Smshlyn	GetInterface,
362e3724c38Smshlyn	UnregisterInterface,
363e3724c38Smshlyn	ControlInterface,
364e3724c38Smshlyn	GetInterfaces,
365e3724c38Smshlyn	CountInterfaces,
366e3724c38Smshlyn	EnableReports,
367e3724c38Smshlyn	DisableReports,
368e3724c38Smshlyn	DoesReport
369e3724c38Smshlyn};
370e3724c38Smshlyn
371e3724c38Smshlyn
372e3724c38Smshlynmodule_info* modules[] = {
373e3724c38Smshlyn	(module_info*)&sKPPPManagerModule,
374e3724c38Smshlyn	NULL
375e3724c38Smshlyn};
376