Changed PPP interface manager API to support interface names and profiles.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6280 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald
2004-01-25 12:50:07 +00:00
parent 96fea92979
commit bdf55481a8
4 changed files with 171 additions and 50 deletions
@@ -3,6 +3,7 @@ SubDir OBOS_TOP src add-ons kernel network interfaces ppp ;
UsePrivateHeaders net ; UsePrivateHeaders net ;
UsePrivateHeaders [ FDirName kernel ] ; UsePrivateHeaders [ FDirName kernel ] ;
UsePrivateHeaders [ FDirName kernel util ] ; UsePrivateHeaders [ FDirName kernel util ] ;
UseHeaders [ FDirName $(OBOS_TOP) src add-ons kernel network ppp shared libkernelppp ] ;
UseHeaders [ FDirName $(OBOS_TOP) src add-ons kernel network ppp shared libkernelppp headers ] ; UseHeaders [ FDirName $(OBOS_TOP) src add-ons kernel network ppp shared libkernelppp headers ] ;
@@ -5,9 +5,12 @@
// Copyright (c) 2003-2004 Waldemar Kornewald, [email protected] // Copyright (c) 2003-2004 Waldemar Kornewald, [email protected]
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
#include <cstdio>
#include "PPPManager.h" #include "PPPManager.h"
#include <PPPControl.h> #include <PPPControl.h>
#include <KPPPUtils.h> #include <KPPPUtils.h>
#include <settings_tools.h>
#include <LockerHelper.h> #include <LockerHelper.h>
@@ -15,7 +18,7 @@
#include <sys/sockio.h> #include <sys/sockio.h>
static const char sPPPIfNameBase[] = "ppp"; static const char sKPPPIfNameBase[] = "ppp";
static static
@@ -191,7 +194,7 @@ PPPManager::Output(ifnet *ifp, struct mbuf *buf, struct sockaddr *dst,
} }
int32 result = B_ERROR; int32 result = B_ERROR;
PPPProtocol *protocol = entry->interface->FirstProtocol(); KPPPProtocol *protocol = entry->interface->FirstProtocol();
for(; protocol; protocol = protocol->NextProtocol()) { for(; protocol; protocol = protocol->NextProtocol()) {
if(!protocol->IsEnabled() || protocol->AddressFamily() != dst->sa_family) if(!protocol->IsEnabled() || protocol->AddressFamily() != dst->sa_family)
continue; continue;
@@ -254,54 +257,39 @@ PPPManager::Control(ifnet *ifp, ulong cmd, caddr_t data)
ppp_interface_id ppp_interface_id
PPPManager::CreateInterface(const driver_settings *settings, PPPManager::CreateInterface(const driver_settings *settings,
const driver_settings *profile = NULL,
ppp_interface_id parentID = PPP_UNDEFINED_INTERFACE_ID) ppp_interface_id parentID = PPP_UNDEFINED_INTERFACE_ID)
{ {
#if DEBUG return _CreateInterface(NULL, settings, profile, parentID);
dprintf("PPPManager: CreateInterface()\n"); }
#endif
LockerHelper locker(fLock); ppp_interface_id
PPPManager::CreateInterfaceWithName(const char *name,
ppp_interface_entry *parentEntry = EntryFor(parentID); const driver_settings *profile = NULL,
if(parentID != PPP_UNDEFINED_INTERFACE_ID && !parentEntry) ppp_interface_id parentID = PPP_UNDEFINED_INTERFACE_ID)
{
if(!name)
return PPP_UNDEFINED_INTERFACE_ID; return PPP_UNDEFINED_INTERFACE_ID;
// the day when NextID() returns 0 will come, be prepared! ;) char path[B_PATH_NAME_LENGTH];
ppp_interface_id id = NextID(); sprintf(path, "pppidf/%s", name);
if(id == PPP_UNDEFINED_INTERFACE_ID) // XXX: TODO: change base path to "/etc/ppp" when settings API supports it
id = NextID();
ppp_interface_entry *entry = new ppp_interface_entry; void *handle = load_driver_settings(path);
entry->accessing = 1; if(!handle)
entry->deleting = false; return PPP_UNDEFINED_INTERFACE_ID;
fEntries.AddItem(entry);
// nothing bad can happen because we are in a locked section here
new PPPInterface(entry, id, settings, parentEntry ? parentEntry->interface : NULL); const driver_settings *settings = get_driver_settings(handle);
// PPPInterface will add itself to the entry (no need to do it here) if(!settings) {
if(entry->interface->InitCheck() != B_OK) { unload_driver_settings(handle);
delete entry->interface;
delete entry;
return PPP_UNDEFINED_INTERFACE_ID; return PPP_UNDEFINED_INTERFACE_ID;
} }
locker.UnlockNow(); ppp_interface_id result = _CreateInterface(name, settings, profile, parentID);
// it is safe to access the manager from userland unload_driver_settings(handle);
if(!Report(PPP_MANAGER_REPORT, PPP_REPORT_INTERFACE_CREATED, return result;
&id, sizeof(ppp_interface_id))) {
DeleteInterface(id);
--entry->accessing;
return PPP_UNDEFINED_INTERFACE_ID;
}
// notify handlers that interface has been created and they can initialize it now
entry->interface->StateMachine().DownProtocols();
entry->interface->StateMachine().ResetLCPHandlers();
--entry->accessing;
return id;
} }
@@ -376,7 +364,7 @@ PPPManager::RegisterInterface(ppp_interface_id ID)
memset(ifp, 0, sizeof(ifnet)); memset(ifp, 0, sizeof(ifnet));
ifp->devid = -1; ifp->devid = -1;
ifp->if_type = IFT_PPP; ifp->if_type = IFT_PPP;
ifp->name = sPPPIfNameBase; ifp->name = sKPPPIfNameBase;
ifp->if_unit = FindUnit(); ifp->if_unit = FindUnit();
ifp->if_flags = IFF_POINTOPOINT; ifp->if_flags = IFF_POINTOPOINT;
ifp->rx_thread = ifp->tx_thread = -1; ifp->rx_thread = ifp->tx_thread = -1;
@@ -428,14 +416,29 @@ PPPManager::Control(uint32 op, void *data, size_t length)
switch(op) { switch(op) {
case PPPC_CREATE_INTERFACE: { case PPPC_CREATE_INTERFACE: {
if(length < sizeof(ppp_interface_settings_info) || !data) if(length < sizeof(ppp_interface_description_info) || !data)
return B_ERROR; return B_ERROR;
ppp_interface_settings_info *info = (ppp_interface_settings_info*) data; ppp_interface_description_info *info
if(!info->settings) = (ppp_interface_description_info*) data;
if(!info->u.settings)
return B_ERROR; return B_ERROR;
info->interface = CreateInterface(info->settings); info->interface = CreateInterface(info->u.settings, info->profile);
// parents cannot be set from userland
return info->interface != PPP_UNDEFINED_INTERFACE_ID ? B_OK : B_ERROR;
} break;
case PPPC_CREATE_INTERFACE_WITH_NAME: {
if(length < sizeof(ppp_interface_description_info) || !data)
return B_ERROR;
ppp_interface_description_info *info
= (ppp_interface_description_info*) data;
if(!info->u.name)
return B_ERROR;
info->interface = CreateInterfaceWithName(info->u.name, info->profile);
// parents cannot be set from userland // parents cannot be set from userland
return info->interface != PPP_UNDEFINED_INTERFACE_ID ? B_OK : B_ERROR; return info->interface != PPP_UNDEFINED_INTERFACE_ID ? B_OK : B_ERROR;
} break; } break;
@@ -513,6 +516,24 @@ PPPManager::Control(uint32 op, void *data, size_t length)
return CountInterfaces(*(ppp_interface_filter*)data); return CountInterfaces(*(ppp_interface_filter*)data);
break; break;
case PPPC_FIND_INTERFACE_WITH_SETTINGS: {
if(length < sizeof(ppp_interface_description_info) || !data)
return B_ERROR;
ppp_interface_description_info *info
= (ppp_interface_description_info*) data;
if(!info->u.settings)
return B_ERROR;
ppp_interface_entry *entry = EntryFor(info->u.settings);
if(entry)
info->interface = entry->interface->ID();
else {
info->interface = PPP_UNDEFINED_INTERFACE_ID;
return B_ERROR;
}
} break;
case PPPC_ENABLE_REPORTS: { case PPPC_ENABLE_REPORTS: {
if(length < sizeof(ppp_report_request) || !data) if(length < sizeof(ppp_report_request) || !data)
return B_ERROR; return B_ERROR;
@@ -688,6 +709,27 @@ PPPManager::EntryFor(ifnet *ifp, int32 *saveIndex = NULL) const
} }
ppp_interface_entry*
PPPManager::EntryFor(const driver_settings *settings) const
{
if(!settings)
return NULL;
#if DEBUG
dprintf("PPPManager: EntryFor(settings)\n");
#endif
ppp_interface_entry *entry;
for(int32 index = 0; index < fEntries.CountItems(); index++) {
entry = fEntries.ItemAt(index);
if(entry && equal_interface_settings(entry->interface->Settings(), settings))
return entry;
}
return NULL;
}
static static
int int
greater(const void *a, const void *b) greater(const void *a, const void *b)
@@ -696,6 +738,61 @@ greater(const void *a, const void *b)
} }
// used by the public CreateInterface() methods
ppp_interface_id
PPPManager::_CreateInterface(const char *name, const driver_settings *settings,
const driver_settings *profile, ppp_interface_id parentID)
{
#if DEBUG
dprintf("PPPManager: CreateInterface(%s)\n", name ? name : "Unnamed");
#endif
LockerHelper locker(fLock);
ppp_interface_entry *parentEntry = EntryFor(parentID);
if(parentID != PPP_UNDEFINED_INTERFACE_ID && !parentEntry)
return PPP_UNDEFINED_INTERFACE_ID;
// the day when NextID() returns 0 will come, be prepared! ;)
ppp_interface_id id = NextID();
if(id == PPP_UNDEFINED_INTERFACE_ID)
id = NextID();
ppp_interface_entry *entry = new ppp_interface_entry;
entry->accessing = 1;
entry->deleting = false;
fEntries.AddItem(entry);
// nothing bad can happen because we are in a locked section here
new KPPPInterface(name, entry, id, settings, profile,
parentEntry ? parentEntry->interface : NULL);
// KPPPInterface will add itself to the entry (no need to do it here)
if(entry->interface->InitCheck() != B_OK) {
delete entry->interface;
delete entry;
return PPP_UNDEFINED_INTERFACE_ID;
}
locker.UnlockNow();
// it is safe to access the manager from userland
if(!Report(PPP_MANAGER_REPORT, PPP_REPORT_INTERFACE_CREATED,
&id, sizeof(ppp_interface_id))) {
DeleteInterface(id);
--entry->accessing;
return PPP_UNDEFINED_INTERFACE_ID;
}
// notify handlers that interface has been created and they can initialize it now
entry->interface->StateMachine().DownProtocols();
entry->interface->StateMachine().ResetLCPHandlers();
--entry->accessing;
return id;
}
int32 int32
PPPManager::FindUnit() const PPPManager::FindUnit() const
{ {
@@ -31,6 +31,10 @@ class PPPManager {
int32 Control(ifnet *ifp, ulong cmd, caddr_t data); int32 Control(ifnet *ifp, ulong cmd, caddr_t data);
ppp_interface_id CreateInterface(const driver_settings *settings, ppp_interface_id CreateInterface(const driver_settings *settings,
const driver_settings *profile = NULL,
ppp_interface_id parentID = PPP_UNDEFINED_INTERFACE_ID);
ppp_interface_id CreateInterfaceWithName(const char *name,
const driver_settings *profile = NULL,
ppp_interface_id parentID = PPP_UNDEFINED_INTERFACE_ID); ppp_interface_id parentID = PPP_UNDEFINED_INTERFACE_ID);
bool DeleteInterface(ppp_interface_id ID); bool DeleteInterface(ppp_interface_id ID);
bool RemoveInterface(ppp_interface_id ID); bool RemoveInterface(ppp_interface_id ID);
@@ -46,14 +50,16 @@ class PPPManager {
ppp_interface_filter filter = PPP_REGISTERED_INTERFACES); ppp_interface_filter filter = PPP_REGISTERED_INTERFACES);
int32 CountInterfaces(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES); int32 CountInterfaces(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES);
PPPReportManager& ReportManager() KPPPReportManager& ReportManager()
{ return fReportManager; } { return fReportManager; }
bool Report(ppp_report_type type, int32 code, void *data, int32 length) bool Report(ppp_report_type type, int32 code, void *data, int32 length)
{ return ReportManager().Report(type, code, data, length); } { return ReportManager().Report(type, code, data, length); }
// returns false if reply was bad (or an error occured) // returns false if reply was bad (or an error occured)
ppp_interface_entry *EntryFor(ppp_interface_id ID, int32 *saveIndex = NULL) const; ppp_interface_entry *EntryFor(ppp_interface_id ID,
int32 *saveIndex = NULL) const;
ppp_interface_entry *EntryFor(ifnet *ifp, int32 *saveIndex = NULL) const; ppp_interface_entry *EntryFor(ifnet *ifp, int32 *saveIndex = NULL) const;
ppp_interface_entry *EntryFor(const driver_settings *settings) const;
ppp_interface_id NextID() ppp_interface_id NextID()
{ return (ppp_interface_id) atomic_add((int32*) &fNextID, 1); } { return (ppp_interface_id) atomic_add((int32*) &fNextID, 1); }
@@ -62,11 +68,14 @@ class PPPManager {
void Pulse(); void Pulse();
private: private:
ppp_interface_id _CreateInterface(const char *name,
const driver_settings *settings, const driver_settings *profile,
ppp_interface_id parentID);
int32 FindUnit() const; int32 FindUnit() const;
private: private:
BLocker fLock, fReportLock; BLocker fLock, fReportLock;
PPPReportManager fReportManager; KPPPReportManager fReportManager;
TemplateList<ppp_interface_entry*> fEntries; TemplateList<ppp_interface_entry*> fEntries;
ppp_interface_id fNextID; ppp_interface_id fNextID;
thread_id fDeleterThread, fPulseTimer; thread_id fDeleterThread, fPulseTimer;
@@ -88,10 +88,23 @@ ppp_control(uint32 op, void *data, size_t length)
static static
ppp_interface_id ppp_interface_id
CreateInterface(const driver_settings *settings, ppp_interface_id parent) CreateInterface(const driver_settings *settings, const driver_settings *profile,
ppp_interface_id parent)
{ {
if(sManager) if(sManager)
return sManager->CreateInterface(settings, parent); return sManager->CreateInterface(settings, profile, parent);
else
return PPP_UNDEFINED_INTERFACE_ID;
}
static
ppp_interface_id
CreateInterfaceWithName(const char *name, const driver_settings *profile,
ppp_interface_id parent)
{
if(sManager)
return sManager->CreateInterfaceWithName(name, profile, parent);
else else
return PPP_UNDEFINED_INTERFACE_ID; return PPP_UNDEFINED_INTERFACE_ID;
} }
@@ -216,6 +229,7 @@ ppp_interface_module_info ppp_interface_module = {
ppp_control ppp_control
}, },
CreateInterface, CreateInterface,
CreateInterfaceWithName,
DeleteInterface, DeleteInterface,
RemoveInterface, RemoveInterface,
RegisterInterface, RegisterInterface,