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