diff --git a/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp b/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp index 3ccd8df798..1048d810c7 100644 --- a/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp +++ b/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp @@ -17,8 +17,8 @@ #ifdef _KERNEL_MODE -#define spawn_thread spawn_kernel_thread -#define printf dprintf + #define spawn_thread spawn_kernel_thread + #define printf dprintf #endif @@ -107,6 +107,10 @@ PPPManager::PPPManager() : fReportManager(fReportLock), fNextID(1) { +#if DEBUG + printf("PPPManager: Constructor\n"); +#endif + fDeleterThread = spawn_thread(deleter_thread, "PPPManager: deleter_thread", B_NORMAL_PRIORITY, this); resume_thread(fDeleterThread); @@ -116,6 +120,10 @@ PPPManager::PPPManager() PPPManager::~PPPManager() { +#if DEBUG + printf("PPPManager: Destructor\n"); +#endif + int32 tmp; send_data(fDeleterThread, 0, NULL, 0); // notify deleter_thread that we are being destroyed @@ -136,6 +144,10 @@ PPPManager::~PPPManager() int32 PPPManager::Stop(ifnet *ifp) { +#if DEBUG + printf("PPPManager: Stop(%s)\n", ifp ? ifp->if_name : "Unknown"); +#endif + LockerHelper locker(fLock); interface_entry *entry = EntryFor(ifp); @@ -152,6 +164,10 @@ int32 PPPManager::Output(ifnet *ifp, struct mbuf *buf, struct sockaddr *dst, struct rtentry *rt0) { +#if DEBUG + printf("PPPManager: Output(%s)\n", ifp ? ifp->if_name : "Unknown"); +#endif + if(dst->sa_family == AF_UNSPEC) return B_ERROR; @@ -193,6 +209,10 @@ PPPManager::Output(ifnet *ifp, struct mbuf *buf, struct sockaddr *dst, int32 PPPManager::Control(ifnet *ifp, ulong cmd, caddr_t data) { +#if DEBUG + printf("PPPManager: Control(%s)\n", ifp ? ifp->if_name : "Unknown"); +#endif + LockerHelper locker(fLock); interface_entry *entry = EntryFor(ifp); if(!entry || entry->deleting) @@ -226,6 +246,10 @@ interface_id PPPManager::CreateInterface(const driver_settings *settings, interface_id parentID = PPP_UNDEFINED_INTERFACE_ID) { +#if DEBUG + printf("PPPManager: CreateInterface()\n"); +#endif + LockerHelper locker(fLock); interface_entry *parentEntry = EntryFor(parentID); @@ -263,6 +287,10 @@ PPPManager::CreateInterface(const driver_settings *settings, void PPPManager::DeleteInterface(interface_id ID) { +#if DEBUG + printf("PPPManager: DeleteInterface(%ld)\n", ID); +#endif + // This only marks the interface for deletion. // Our deleter_thread does the real work. LockerHelper locker(fLock); @@ -276,6 +304,10 @@ PPPManager::DeleteInterface(interface_id ID) void PPPManager::RemoveInterface(interface_id ID) { +#if DEBUG + printf("PPPManager: RemoveInterface(%ld)\n", ID); +#endif + LockerHelper locker(fLock); int32 index; @@ -293,6 +325,10 @@ PPPManager::RemoveInterface(interface_id ID) ifnet* PPPManager::RegisterInterface(interface_id ID) { +#if DEBUG + printf("PPPManager: RegisterInterface(%ld)\n", ID); +#endif + LockerHelper locker(fLock); interface_entry *entry = EntryFor(ID); @@ -316,6 +352,11 @@ PPPManager::RegisterInterface(interface_id ID) ifp->output = ppp_ifnet_output; ifp->ioctl = ppp_ifnet_ioctl; +#if DEBUG + printf("PPPManager::DeleteInterface(): Created new ifnet: %s%d\n", + ifp->name, ifp->if_unit); +#endif + if_attach(ifp); return ifp; } @@ -324,6 +365,10 @@ PPPManager::RegisterInterface(interface_id ID) bool PPPManager::UnregisterInterface(interface_id ID) { +#if DEBUG + printf("PPPManager: UnregisterInterface(%ld)\n", ID); +#endif + LockerHelper locker(fLock); interface_entry *entry = EntryFor(ID); @@ -342,6 +387,10 @@ PPPManager::UnregisterInterface(interface_id ID) status_t PPPManager::Control(uint32 op, void *data, size_t length) { +#if DEBUG + printf("PPPManager: Control(%ld)\n", op); +#endif + // this method is intended for use by userland applications switch(op) { @@ -454,6 +503,10 @@ PPPManager::Control(uint32 op, void *data, size_t length) status_t PPPManager::ControlInterface(interface_id ID, uint32 op, void *data, size_t length) { +#if DEBUG + printf("PPPManager: ControlInterface(%ld)\n", ID); +#endif + LockerHelper locker(fLock); interface_entry *entry = EntryFor(ID); @@ -468,6 +521,10 @@ int32 PPPManager::GetInterfaces(interface_id *interfaces, int32 count, ppp_interface_filter filter = PPP_REGISTERED_INTERFACES) { +#if DEBUG + printf("PPPManager: GetInterfaces()\n"); +#endif + LockerHelper locker(fLock); int32 item = 0; @@ -507,6 +564,10 @@ PPPManager::GetInterfaces(interface_id *interfaces, int32 count, int32 PPPManager::CountInterfaces(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES) { +#if DEBUG + printf("PPPManager: CountInterfaces()\n"); +#endif + LockerHelper locker(fLock); if(filter == PPP_ALL_INTERFACES) @@ -544,6 +605,10 @@ PPPManager::CountInterfaces(ppp_interface_filter filter = PPP_REGISTERED_INTERFA interface_entry* PPPManager::EntryFor(interface_id ID, int32 *saveIndex = NULL) const { +#if DEBUG + printf("PPPManager: EntryFor(%ld)\n", ID); +#endif + if(ID == PPP_UNDEFINED_INTERFACE_ID) return NULL; @@ -567,6 +632,10 @@ PPPManager::EntryFor(ifnet *ifp, int32 *saveIndex = NULL) const if(!ifp) return NULL; +#if DEBUG + printf("PPPManager: EntryFor(%s%d)\n", ifp->name, ifp->if_unit); +#endif + interface_entry *entry; for(int32 index = 0; index < fEntries.CountItems(); index++) { entry = fEntries.ItemAt(index); diff --git a/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp b/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp index 146fe523f1..32da78f15e 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp +++ b/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp @@ -36,10 +36,6 @@ PPPoEDevice::PPPoEDevice(PPPInterface& interface, driver_parameter *settings) printf("PPPoEDevice: Constructor\n"); if(!settings || !settings->parameters) printf("PPPoEDevice::ctor: No settings!\n"); - else if(settings->parameter_count > 0 && settings->parameters[0].value_count > 0) - printf("PPPoEDevice::ctor: Value0: %s\n", settings->parameters[0].values[0]); - else - printf("PPPoEDevice::ctor: No values!\n"); #endif memset(fPeer, 0xFF, sizeof(fPeer)); @@ -56,7 +52,8 @@ PPPoEDevice::PPPoEDevice(PPPInterface& interface, driver_parameter *settings) ifnet *current = get_interfaces(); for(; current; current = current->if_next) { - if(current->if_name && !strcmp(current->if_name, interfaceName)) { + if(current->if_type == IFT_ETHER && current->if_name + && !strcmp(current->if_name, interfaceName)) { #if DEBUG printf("PPPoEDevice::ctor: found ethernet interface\n"); #endif diff --git a/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp b/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp index ccf1729c08..718fddaf88 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp +++ b/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp @@ -96,10 +96,16 @@ add_to(PPPInterface& mainInterface, PPPInterface *subInterface, PPPoEDevice *device; bool success; if(subInterface) { +#if DEBUG + printf("PPPoE: add_to(): Adding to subInterface\n"); +#endif device = new PPPoEDevice(*subInterface, settings); success = subInterface->SetDevice(device); - } else - device = new PPPoEDevice(mainInterface, settings); { + } else { +#if DEBUG + printf("PPPoE: add_to(): Adding to mainInterface\n"); +#endif + device = new PPPoEDevice(mainInterface, settings); success = mainInterface.SetDevice(device); } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp index f374f5a4e0..39c79ba38a 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp @@ -58,6 +58,8 @@ status_t redial_thread(void *data); // other functions status_t interface_deleter_thread(void *data); +status_t call_open_event_thread(void *data); +status_t call_close_event_thread(void *data); PPPInterface::PPPInterface(uint32 ID, const driver_settings *settings, @@ -67,6 +69,8 @@ PPPInterface::PPPInterface(uint32 ID, const driver_settings *settings, fSettings(dup_driver_settings(settings)), fIfnet(NULL), fUpThread(-1), + fOpenEventThread(-1), + fCloseEventThread(-1), fRedialThread(-1), fDialRetry(0), fDialRetriesLimit(0), @@ -182,12 +186,12 @@ PPPInterface::PPPInterface(uint32 ID, const driver_settings *settings, PPPInterface::~PPPInterface() { - ++fDeleteCounter; - #if DEBUG printf("PPPInterface: Destructor\n"); #endif + ++fDeleteCounter; + // make sure we are not accessible by any thread before we continue UnregisterInterface(); @@ -211,6 +215,8 @@ PPPInterface::~PPPInterface() send_data_with_timeout(fRedialThread, 0, NULL, 0, 200); // tell thread that we are being destroyed (200ms timeout) wait_for_thread(fRedialThread, &tmp); + wait_for_thread(fOpenEventThread, &tmp); + wait_for_thread(fCloseEventThread, &tmp); while(CountChildren()) delete ChildAt(0); @@ -459,7 +465,7 @@ bool PPPInterface::SetDevice(PPPDevice *device) { #if DEBUG - printf("PPPInterface: SetDevice()\n"); + printf("PPPInterface: SetDevice(%p)\n", device); #endif if(device && &device->Interface() != this) @@ -715,7 +721,7 @@ PPPInterface::SetAutoRedial(bool autoRedial = true) printf("PPPInterface: SetAutoRedial(%s)\n", autoRedial ? "true" : "false"); #endif - if(Mode() == PPP_CLIENT_MODE) + if(Mode() != PPP_CLIENT_MODE) return; LockerHelper locker(fLock); @@ -732,7 +738,6 @@ PPPInterface::SetDialOnDemand(bool dialOnDemand = true) #if DEBUG printf("PPPInterface: SetDialOnDemand(%s)\n", dialOnDemand ? "true" : "false"); - printf("PPPInterface::SetDialOnDemand(): %s\n", fDialOnDemand ? "true" : "false"); #endif // Only clients support DialOnDemand. @@ -749,10 +754,6 @@ PPPInterface::SetDialOnDemand(bool dialOnDemand = true) fDialOnDemand = dialOnDemand; -#if DEBUG - printf("PPPInterface::SetDialOnDemand() done: %s\n", fDialOnDemand?"true":"false"); -#endif - // Do not allow changes when we are disconnected (only main interfaces). // This would make no sense because // - enabling: this cannot happen because hidden interfaces are deleted if they @@ -810,22 +811,31 @@ PPPInterface::Up() // One thread has to do the real task while all other threads are observers. // Lock needs timeout because destructor could have locked the interface. - while(!fLock.LockWithTimeout(100000) != B_NO_ERROR) + while(fLock.LockWithTimeout(100000) != B_NO_ERROR) if(fDeleteCounter > 0) return false; if(fUpThread == -1) fUpThread = me; ReportManager().EnableReports(PPP_CONNECTION_REPORT, me, PPP_WAIT_FOR_REPLY); - fLock.Unlock(); - // fUpThread tells the state machine to go up - if(me == fUpThread || me == fRedialThread) - StateMachine().OpenEvent(); + // fUpThread/fRedialThread tells the state machine to go up (using a new thread + // because we might not receive report messages otherwise) + if(me == fUpThread || me == fRedialThread) { + if(fOpenEventThread != -1) { + int32 tmp; + wait_for_thread(fOpenEventThread, &tmp); + } + fOpenEventThread = spawn_thread(call_open_event_thread, + "PPPInterface: call_open_event_thread", B_NORMAL_PRIORITY, this); + resume_thread(fOpenEventThread); + } + fLock.Unlock(); if(me == fRedialThread && me != fUpThread) return true; - // the redial thread is doing a DialRetry in this case + // the redial thread is doing a DialRetry in this case (fUpThread + // is waiting for new reports) while(true) { if(IsUp()) { @@ -1004,12 +1014,18 @@ PPPInterface::Down() return true; ReportManager().EnableReports(PPP_CONNECTION_REPORT, find_thread(NULL)); - locker.UnlockNow(); thread_id sender; ppp_report_packet report; - StateMachine().CloseEvent(); + if(fCloseEventThread != -1) { + int32 tmp; + wait_for_thread(fCloseEventThread, &tmp); + } + fCloseEventThread = spawn_thread(call_close_event_thread, + "PPPInterface: call_close_event_thread", B_NORMAL_PRIORITY, this); + resume_thread(fCloseEventThread); + locker.UnlockNow(); while(true) { if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE) @@ -1351,10 +1367,6 @@ PPPInterface::RegisterInterface() LockerHelper locker(fLock); - if(InitCheck() != B_OK) - return false; - // we cannot register if something is wrong - // only MainInterfaces get an ifnet if(IsMultilink() && Parent() && Parent()->RegisterInterface()) return true; @@ -1583,14 +1595,56 @@ redial_thread(void *data) // which is only defined here (the real class is defined in the ppp interface module). class PPPManager { public: - PPPManager(PPPInterface *interface) - { if(interface) delete interface; } + PPPManager() {} + + void Delete(PPPInterface *interface) + { delete interface; } + void CallOpenEvent(PPPInterface *interface) + { + while(interface->fLock.LockWithTimeout(100000) != B_NO_ERROR) + if(interface->fDeleteCounter > 0) + return; + interface->CallOpenEvent(); + interface->fOpenEventThread = -1; + interface->fLock.Unlock(); + } + void CallCloseEvent(PPPInterface *interface) + { + while(interface->fLock.LockWithTimeout(100000) != B_NO_ERROR) + if(interface->fDeleteCounter > 0) + return; + interface->CallCloseEvent(); + interface->fCloseEventThread = -1; + interface->fLock.Unlock(); + } }; + status_t interface_deleter_thread(void *data) { - PPPManager((PPPInterface*) data); + PPPManager manager; + manager.Delete((PPPInterface*) data); + + return B_OK; +} + + +status_t +call_open_event_thread(void *data) +{ + PPPManager manager; + manager.CallOpenEvent((PPPInterface*) data); + + return B_OK; +} + + +status_t +call_close_event_thread(void *data) +{ + PPPManager manager; + manager.CallCloseEvent((PPPInterface*) data); return B_OK; } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp index 5d3f9e8710..48b3ecb116 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp @@ -425,7 +425,7 @@ PPPStateMachine::UpFailedEvent() Interface().Parent()->StateMachine().UpFailedEvent(Interface()); NewPhase(PPP_DOWN_PHASE); - // tell DownEvent() that we do not need to redial + // tell DownEvent() that it should not create a connection-lost-report DownEvent(); break; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h index 8ea2502974..df40a09cef 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h @@ -187,6 +187,12 @@ class PPPInterface : public PPPLayer { void CalculateInterfaceMTU(); void CalculateBaudRate(); + // these two methods are used by the open/close_event_threads + void CallOpenEvent() + { StateMachine().OpenEvent(); } + void CallCloseEvent() + { StateMachine().CloseEvent(); } + void Redial(uint32 delay); // multilink methods @@ -199,7 +205,7 @@ class PPPInterface : public PPPLayer { driver_settings *fSettings; struct ifnet *fIfnet; - thread_id fUpThread; + thread_id fUpThread, fOpenEventThread, fCloseEventThread; thread_id fRedialThread; uint32 fDialRetry, fDialRetriesLimit; diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp b/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp index c532e0fff4..56cb27d996 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp @@ -52,7 +52,11 @@ PPPInterface::SetTo(interface_id ID) fID = ID; - return Control(PPPC_GET_INTERFACE_INFO, &fInfo, sizeof(fInfo)); + status_t error = Control(PPPC_GET_INTERFACE_INFO, &fInfo, sizeof(fInfo)); + if(error != B_OK) + fID = PPP_UNDEFINED_INTERFACE_ID; + + return error; } @@ -80,7 +84,7 @@ PPPInterface::Control(uint32 op, void *data, size_t length) const bool -PPPInterface::GetInterfaceInfo(ppp_interface_info *info) const +PPPInterface::GetInterfaceInfo(ppp_interface_info_t *info) const { if(InitCheck() != B_OK || !info) return false; diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp b/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp index 1c0a1b0e02..e3fd48327e 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp @@ -133,12 +133,12 @@ PPPManager::InterfaceWithSettings(const driver_settings *settings) const interface_id id = PPP_UNDEFINED_INTERFACE_ID; PPPInterface interface; - ppp_interface_info info; + ppp_interface_info_t info; for(int32 index = 0; index < count; index++) { interface.SetTo(interfaces[index]); if(interface.InitCheck() == B_OK && interface.GetInterfaceInfo(&info) - && equal_driver_settings(settings, info.settings)) { + && equal_driver_settings(settings, info.info.settings)) { id = interface.ID(); break; } @@ -161,12 +161,12 @@ PPPManager::InterfaceWithUnit(int32 if_unit) interface_id id = PPP_UNDEFINED_INTERFACE_ID; PPPInterface interface; - ppp_interface_info info; + ppp_interface_info_t info; for(int32 index = 0; index < count; index++) { interface.SetTo(interfaces[index]); if(interface.InitCheck() == B_OK && interface.GetInterfaceInfo(&info) - && info.if_unit == if_unit) { + && info.info.if_unit == if_unit) { id = interface.ID(); break; } diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPInterface.h b/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPInterface.h index 969825a15c..4ef636cb88 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPInterface.h +++ b/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPInterface.h @@ -25,7 +25,7 @@ class PPPInterface { status_t Control(uint32 op, void *data, size_t length) const; - bool GetInterfaceInfo(ppp_interface_info *info) const; + bool GetInterfaceInfo(ppp_interface_info_t *info) const; bool Up() const; bool Down() const; @@ -43,7 +43,7 @@ class PPPInterface { interface_id fID; int fFD; - ppp_interface_info fInfo; + ppp_interface_info_t fInfo; };