/* * Copyright 2006-2017, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Axel Dörfler, axeld@pinc-software.de * Lin Longzhou, linlongzhou@163.com * Alexander von Gluck IV, kallisti5@unixzen.com */ #include #include #include #include #include #include #include #include #include struct entry_private : ppp_interface_entry, DoublyLinkedListLinkImpl { }; static DoublyLinkedList sEntryList; net_buffer_module_info* gBufferModule = NULL; net_stack_module_info* gStackModule = NULL; // static struct net_interface* sinterface; static mutex sListLock; static uint32 ppp_interface_count; // #pragma mark - static KPPPInterface* GetInterface(ppp_interface_id ID); static ppp_interface_id CreateInterface(const driver_settings* settings, ppp_interface_id parentID) { MutexLocker _(sListLock); // auto_lock if (parentID > 0) { TRACE("Not support Multi_Link yet!\n"); return 0l; } if (settings == NULL) { TRACE("No driver_settings yet!\n"); return 0l; } ppp_interface_count++; if (GetInterface(ppp_interface_count) != NULL) { TRACE("PPP Interface already exists!\n"); return 0l; } entry_private* pentry = new (std::nothrow) entry_private; memset(pentry, 0, sizeof(entry_private)); pentry->accessing = ppp_interface_count; sEntryList.Add(pentry); KPPPInterface* device = new (std::nothrow) KPPPInterface(NULL, pentry, ppp_interface_count, NULL, NULL); if (device == NULL || pentry == NULL) { TRACE("device or pentry is NULL\n"); ppp_interface_count--; return 0l; } TRACE("setting ppp_interface_count %" B_PRIu32 "\n", ppp_interface_count); return ppp_interface_count; // only support 1 ppp connection right now } static ppp_interface_id CreateInterfaceWithName(const char* name, ppp_interface_id parentID) { MutexLocker _(sListLock); // auto_lock if (parentID > 0) { dprintf("Not support Multi_Link yet!\n"); return(0); } if (strncmp(name, "ppp", 3)) { dprintf("%s is not ppp device!\n", name); return(0); } ppp_interface_count++; if (GetInterface(ppp_interface_count) != NULL) { TRACE("PPP Interface already exists!\n"); return 0l; } entry_private* pentry = new (std::nothrow) entry_private; memset(pentry, 0, sizeof(entry_private)); pentry->accessing = ppp_interface_count; sEntryList.Add(pentry); KPPPInterface* device = new (std::nothrow) KPPPInterface(name, pentry, ppp_interface_count, NULL, NULL); if (device == NULL || pentry == NULL) { TRACE("can not create ppp interface!\n"); ppp_interface_count--; return 0l; } TRACE("setting ppp_interface_count %" B_PRIu32 "\n", ppp_interface_count); return ppp_interface_count; } static bool DeleteInterface(ppp_interface_id ID) { MutexLocker _(sListLock); // auto_lock DoublyLinkedList::Iterator iterator = sEntryList.GetIterator(); while (iterator.HasNext()) { entry_private* pentry = iterator.Next(); if ((ppp_interface_id)pentry->accessing == ID) { pentry->deleting = true; return true; } } return false; } static bool RemoveInterface(ppp_interface_id ID) { MutexLocker _(sListLock); // auto_lock if (ID <= 0 || ID > ppp_interface_count) return false; DoublyLinkedList::Iterator iterator = sEntryList.GetIterator(); while (iterator.HasNext()) { entry_private* pentry = iterator.Next(); if ((ppp_interface_id)pentry->accessing == ID) { pentry->deleting = true; break; } } return false; } static net_device* RegisterInterface(ppp_interface_id ID) { // MutexLocker _(sListLock); // auto_lock entry_private* entry = NULL; DoublyLinkedList::Iterator iterator = sEntryList.GetIterator(); while (iterator.HasNext()) { entry_private* pentry = iterator.Next(); if ((ppp_interface_id)pentry->accessing == ID) { entry = pentry; break; } } if (entry == NULL) return NULL; ppp_device* device = new (std::nothrow) ppp_device; if (device == NULL) return NULL; memset(device, 0, sizeof(ppp_device)); device->KPPP_Interface = entry->interface; return device; } static KPPPInterface* GetInterface(ppp_interface_id ID) { // MutexLocker _(sListLock); // auto_lock DoublyLinkedList::Iterator iterator = sEntryList.GetIterator(); while (iterator.HasNext()) { entry_private* pentry = iterator.Next(); TRACE("testing interface id:%" B_PRId32 "\n", pentry->accessing); if ((ppp_interface_id)(pentry->accessing) == ID) { TRACE("get interface id:%" B_PRId32 "\n", ID); return pentry->interface; } } TRACE("can not get interface id:%" B_PRId32 "\n", ID); return NULL; } static bool UnregisterInterface(ppp_interface_id ID) { MutexLocker _(sListLock); // auto_lock if (ID <= 0 || ID > ppp_interface_count) return false; return true; } static status_t ControlInterface(ppp_interface_id ID, uint32 op, void* data, size_t length) { MutexLocker _(sListLock); // auto_lock if (ID <= 0 || ID > ppp_interface_count) return B_ERROR; DoublyLinkedList::Iterator iterator = sEntryList.GetIterator(); while (iterator.HasNext()) { entry_private* pentry = iterator.Next(); if ((ppp_interface_id)pentry->accessing == ID) return B_OK; } return B_ERROR; } static int32 GetInterfaces(ppp_interface_id* interfaces, int32 count, ppp_interface_filter filter) { MutexLocker _(sListLock); if (count <= 0 || count > (int32)ppp_interface_count) return(0); uint32 ppp_count = 0; DoublyLinkedList::Iterator iterator = sEntryList.GetIterator(); while (iterator.HasNext()) { entry_private* pentry = iterator.Next(); interfaces[ppp_count] = pentry->accessing; ppp_count++; } return ppp_count; } static int32 CountInterfaces(ppp_interface_filter filter) { MutexLocker _(sListLock); // auto_lock uint32 ppp_count = 0; DoublyLinkedList::Iterator iterator = sEntryList.GetIterator(); while (iterator.HasNext()) { iterator.Next(); ppp_count++; } return ppp_count; } static void EnableReports(ppp_report_type type, thread_id thread, int32 flags) { MutexLocker _(sListLock); // auto_lock return; // need more portrait } static void DisableReports(ppp_report_type type, thread_id thread) { MutexLocker _(sListLock); // auto_lock return; // need more portrait } static bool DoesReport(ppp_report_type type, thread_id thread) { MutexLocker _(sListLock); // auto_lock return false; // need more portrait } static status_t KPPPManager_std_ops(int32 op, ...) { switch (op) { case B_MODULE_INIT: mutex_init(&sListLock, "KPPPManager"); new (&sEntryList) DoublyLinkedList; // static C++ objects are not initialized in the module startup ppp_interface_count = 0; if (get_module(NET_STACK_MODULE_NAME, (module_info**)&gStackModule) != B_OK) return B_ERROR; if (get_module(NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule) != B_OK) { put_module(NET_STACK_MODULE_NAME); return B_ERROR; } return B_OK; case B_MODULE_UNINIT: mutex_destroy(&sListLock); put_module(NET_BUFFER_MODULE_NAME); put_module(NET_STACK_MODULE_NAME); return B_OK; default: return B_ERROR; } } static ppp_interface_module_info sKPPPManagerModule = { { PPP_INTERFACE_MODULE_NAME, 0, KPPPManager_std_ops }, CreateInterface, CreateInterfaceWithName, DeleteInterface, RemoveInterface, RegisterInterface, GetInterface, UnregisterInterface, ControlInterface, GetInterfaces, CountInterfaces, EnableReports, DisableReports, DoesReport }; module_info* modules[] = { (module_info*)&sKPPPManagerModule, NULL };