xref: /haiku/src/add-ons/kernel/network/ppp/ppp_manager/KPPPManager.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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 
26 struct entry_private : ppp_interface_entry, DoublyLinkedListLinkImpl<entry_private> {
27 };
28 
29 static DoublyLinkedList<entry_private> sEntryList;
30 
31 net_buffer_module_info* gBufferModule = NULL;
32 net_stack_module_info* gStackModule = NULL;
33 // static struct net_interface* sinterface;
34 static mutex sListLock;
35 static uint32 ppp_interface_count;
36 
37 
38 //	#pragma mark -
39 static KPPPInterface* GetInterface(ppp_interface_id ID);
40 
41 static ppp_interface_id
42 CreateInterface(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 
82 static ppp_interface_id
83 CreateInterfaceWithName(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 
124 static bool
125 DeleteInterface(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 
143 static bool
144 RemoveInterface(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 
164 static net_device*
165 RegisterInterface(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 
195 static KPPPInterface*
196 GetInterface(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 
217 static bool
218 UnregisterInterface(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 
228 static status_t
229 ControlInterface(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 
248 static int32
249 GetInterfaces(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 
270 static int32
271 CountInterfaces(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 
288 static void
289 EnableReports(ppp_report_type type, thread_id thread, int32 flags)
290 {
291 	MutexLocker _(sListLock); // auto_lock
292 
293 	return; // need more portrait
294 }
295 
296 
297 static void
298 DisableReports(ppp_report_type type, thread_id thread)
299 {
300 	MutexLocker _(sListLock); // auto_lock
301 
302 	return; // need more portrait
303 }
304 
305 
306 static bool
307 DoesReport(ppp_report_type type, thread_id thread)
308 {
309 	MutexLocker _(sListLock); // auto_lock
310 
311 	return false; // need more portrait
312 }
313 
314 
315 static status_t
316 KPPPManager_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 
350 static 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 
372 module_info* modules[] = {
373 	(module_info*)&sKPPPManagerModule,
374 	NULL
375 };
376