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