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
CreateInterface(const driver_settings * settings,ppp_interface_id parentID)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
CreateInterfaceWithName(const char * name,ppp_interface_id parentID)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
DeleteInterface(ppp_interface_id ID)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
RemoveInterface(ppp_interface_id ID)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*
RegisterInterface(ppp_interface_id ID)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*
GetInterface(ppp_interface_id ID)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
UnregisterInterface(ppp_interface_id ID)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
ControlInterface(ppp_interface_id ID,uint32 op,void * data,size_t length)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
GetInterfaces(ppp_interface_id * interfaces,int32 count,ppp_interface_filter filter)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
CountInterfaces(ppp_interface_filter filter)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
EnableReports(ppp_report_type type,thread_id thread,int32 flags)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
DisableReports(ppp_report_type type,thread_id thread)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
DoesReport(ppp_report_type type,thread_id thread)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
KPPPManager_std_ops(int32 op,...)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