Finished PPP interface manager module.
TODO: - IPCP protocol module - PAP authentication module - PPPoE device module - pppdial cmd-line app including needed net_stack_driver changes for control() function support - tests, tests, tests :)) git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5040 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -6,50 +6,172 @@
|
|||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
#include "PPPManager.h"
|
#include "PPPManager.h"
|
||||||
|
#include <PPPControl.h>
|
||||||
|
#include <KPPPUtils.h>
|
||||||
|
|
||||||
#include <core_funcs.h>
|
|
||||||
#include <kernel_cpp.h>
|
#include <kernel_cpp.h>
|
||||||
#include <LockerHelper.h>
|
#include <LockerHelper.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
|
||||||
|
|
||||||
static int ppp_ifnet_stop(ifnet *ifp)
|
#ifdef _KERNEL_MODE
|
||||||
{
|
#define spawn_thread spawn_kernel_thread
|
||||||
return B_ERROR;
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ppp_ifnet_output(ifnet *ifp, struct mbuf *buf, struct sockaddr *dst,
|
|
||||||
struct rtentry *rt0)
|
|
||||||
{
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ppp_ifnet_ioctl(struct ifnet *ifp, ulong cmd, caddr_t data)
|
|
||||||
{
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const char ppp_if_name_base[] = "ppp";
|
static const char ppp_if_name_base[] = "ppp";
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
deleter_thread(void *data)
|
||||||
|
{
|
||||||
|
PPPManager *manager = (PPPManager*) data;
|
||||||
|
thread_id sender;
|
||||||
|
int32 code;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
manager->DeleterThreadEvent();
|
||||||
|
|
||||||
|
// check if the manager is being destroyed
|
||||||
|
if(receive_data_with_timeout(&sender, &code, NULL, 0, 50000) == B_OK)
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
pulse_timer(void *data)
|
||||||
|
{
|
||||||
|
((PPPManager*)data)->Pulse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PPPManager::PPPManager()
|
PPPManager::PPPManager()
|
||||||
: fReportManager(fLock),
|
: fReportManager(fReportLock),
|
||||||
fNextID(1)
|
fNextID(1)
|
||||||
{
|
{
|
||||||
|
fDeleterThread = spawn_thread(deleter_thread, "PPPManager: deleter_thread",
|
||||||
|
B_NORMAL_PRIORITY, this);
|
||||||
|
resume_thread(fDeleterThread);
|
||||||
|
fPulseTimer = net_add_timer(pulse_timer, this, PPP_PULSE_RATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PPPManager::~PPPManager()
|
PPPManager::~PPPManager()
|
||||||
{
|
{
|
||||||
|
int32 tmp;
|
||||||
|
send_data(fDeleterThread, 0, NULL, 0);
|
||||||
|
// notify deleter_thread that we are being destroyed
|
||||||
|
wait_for_thread(fDeleterThread, &tmp);
|
||||||
|
net_remove_timer(fPulseTimer);
|
||||||
|
|
||||||
|
// now really delete the interfaces (the deleter_thread is not running)
|
||||||
|
interface_entry *entry;
|
||||||
|
for(int32 index = 0; index < fEntries.CountItems(); index++) {
|
||||||
|
entry = fEntries.ItemAt(index);
|
||||||
|
if(entry)
|
||||||
|
delete entry->interface;
|
||||||
|
delete entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PPPManager::Stop(ifnet *ifp)
|
||||||
|
{
|
||||||
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
|
interface_entry *entry = EntryFor(ifp);
|
||||||
|
if(!entry)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
DeleteInterface(entry->interface->ID());
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PPPManager::Output(ifnet *ifp, struct mbuf *buf, struct sockaddr *dst,
|
||||||
|
struct rtentry *rt0)
|
||||||
|
{
|
||||||
|
if(dst->sa_family == AF_UNSPEC)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
LockerHelper locker(fLock);
|
||||||
|
interface_entry *entry = EntryFor(ifp);
|
||||||
|
if(!entry)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
++entry->accessing;
|
||||||
|
locker.UnlockNow();
|
||||||
|
|
||||||
|
if(ifp->if_flags & (IFF_UP | IFF_RUNNING) != (IFF_UP | IFF_RUNNING)) {
|
||||||
|
m_freem(buf);
|
||||||
|
--entry->accessing;
|
||||||
|
return ENETDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 result = B_ERROR;
|
||||||
|
PPPProtocol *protocol = entry->interface->FirstProtocol();
|
||||||
|
for(; protocol; protocol = protocol->NextProtocol()) {
|
||||||
|
if(!protocol->IsEnabled() || protocol->AddressFamily() != dst->sa_family)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result = protocol->Send(buf, protocol->ProtocolNumber());
|
||||||
|
if(result == PPP_UNHANDLED)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
--entry->accessing;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_freem(buf);
|
||||||
|
--entry->accessing;
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PPPManager::Control(ifnet *ifp, ulong cmd, caddr_t data)
|
||||||
|
{
|
||||||
|
LockerHelper locker(fLock);
|
||||||
|
interface_entry *entry = EntryFor(ifp);
|
||||||
|
if(!entry || entry->deleting)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
++entry->accessing;
|
||||||
|
locker.UnlockNow();
|
||||||
|
|
||||||
|
switch(cmd) {
|
||||||
|
case SIOCSIFFLAGS:
|
||||||
|
if(((ifreq*)data)->ifr_flags & IFF_DOWN)
|
||||||
|
DeleteInterface(entry->interface->ID());
|
||||||
|
else if(((ifreq*)data)->ifr_flags & IFF_UP) {
|
||||||
|
int32 result = entry->interface->Up() ? B_OK : B_ERROR;
|
||||||
|
--entry->accessing;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return entry->interface->StackControl(cmd, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
--entry->accessing;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface_id
|
interface_id
|
||||||
PPPManager::CreateInterface(const driver_settings *settings, interface_id parentID)
|
PPPManager::CreateInterface(const driver_settings *settings,
|
||||||
|
interface_id parentID = PPP_UNDEFINED_INTERFACE_ID)
|
||||||
{
|
{
|
||||||
LockerHelper locker(fLock);
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
@@ -73,6 +195,12 @@ PPPManager::CreateInterface(const driver_settings *settings, interface_id parent
|
|||||||
fEntries.AddItem(entry);
|
fEntries.AddItem(entry);
|
||||||
locker.UnlockNow();
|
locker.UnlockNow();
|
||||||
|
|
||||||
|
if(Report(PPP_MANAGER_REPORT, PPP_REPORT_INTERFACE_CREATED,
|
||||||
|
&id, sizeof(interface_id)) != B_OK) {
|
||||||
|
DeleteInterface(id);
|
||||||
|
return PPP_UNDEFINED_INTERFACE_ID;
|
||||||
|
}
|
||||||
|
|
||||||
if(!entry->interface->DoesDialOnDemand())
|
if(!entry->interface->DoesDialOnDemand())
|
||||||
entry->interface->Up();
|
entry->interface->Up();
|
||||||
|
|
||||||
@@ -98,9 +226,9 @@ PPPManager::RemoveInterface(interface_id ID)
|
|||||||
{
|
{
|
||||||
LockerHelper locker(fLock);
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
int32 index = 0;
|
int32 index;
|
||||||
interface_entry *entry = EntryFor(ID, &index);
|
interface_entry *entry = EntryFor(ID, &index);
|
||||||
if(!entry)
|
if(!entry || entry->deleting)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UnregisterInterface(ID);
|
UnregisterInterface(ID);
|
||||||
@@ -116,7 +244,7 @@ PPPManager::RegisterInterface(interface_id ID)
|
|||||||
LockerHelper locker(fLock);
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
interface_entry *entry = EntryFor(ID);
|
interface_entry *entry = EntryFor(ID);
|
||||||
if(!entry)
|
if(!entry || entry->deleting)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// maybe the interface is already registered
|
// maybe the interface is already registered
|
||||||
@@ -144,21 +272,117 @@ PPPManager::RegisterInterface(interface_id ID)
|
|||||||
bool
|
bool
|
||||||
PPPManager::UnregisterInterface(interface_id ID)
|
PPPManager::UnregisterInterface(interface_id ID)
|
||||||
{
|
{
|
||||||
return false;
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
|
interface_entry *entry = EntryFor(ID);
|
||||||
|
if(!entry)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(entry->interface->Ifnet()) {
|
||||||
|
if_detach(entry->interface->Ifnet());
|
||||||
|
delete entry->interface->Ifnet();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PPPManager::Control(uint32 op, void *data, size_t length)
|
PPPManager::Control(uint32 op, void *data, size_t length)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
// this method is intended for use by userland applications
|
||||||
|
|
||||||
|
switch(op) {
|
||||||
|
case PPPC_CREATE_INTERFACE: {
|
||||||
|
if(length < sizeof(pppc_create_interface_info) || !data)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
pppc_create_interface_info *info = (pppc_create_interface_info*) data;
|
||||||
|
if(!info->settings)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
info->resultID = CreateInterface(info->settings);
|
||||||
|
// parents cannot be set from userland
|
||||||
|
return info->resultID != PPP_UNDEFINED_INTERFACE_ID ? B_OK : B_ERROR;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PPPC_DELETE_INTERFACE:
|
||||||
|
if(length != sizeof(interface_id) || !data)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
DeleteInterface(*(interface_id*)data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPPC_CONTROL_INTERFACE: {
|
||||||
|
if(length < sizeof(ppp_control_info) || !data)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
|
ppp_control_info *control = (ppp_control_info*) data;
|
||||||
|
interface_entry *entry = EntryFor(control->index);
|
||||||
|
if(!entry)
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
|
||||||
|
return entry->interface->Control(control->op, control->data,
|
||||||
|
control->length);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PPPC_GET_INTERFACES: {
|
||||||
|
if(length < sizeof(pppc_get_interfaces_info) || !data)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
pppc_get_interfaces_info *info = (pppc_get_interfaces_info*) data;
|
||||||
|
if(!info->interfaces)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
info->resultCount = GetInterfaces(info->interfaces, info->count,
|
||||||
|
info->filter);
|
||||||
|
return info->resultCount >= 0 ? B_OK : B_ERROR;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PPPC_COUNT_INTERFACES:
|
||||||
|
if(length != sizeof(ppp_interface_filter) || !data)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
return CountInterfaces(*(ppp_interface_filter*)data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPPC_ENABLE_MANAGER_REPORTS: {
|
||||||
|
if(length < sizeof(ppp_report_request) || !data)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
ppp_report_request *request = (ppp_report_request*) data;
|
||||||
|
ReportManager().EnableReports(request->type, request->thread,
|
||||||
|
request->flags);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PPPC_DISABLE_MANAGER_REPORTS: {
|
||||||
|
if(length < sizeof(ppp_report_request) || !data)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
ppp_report_request *request = (ppp_report_request*) data;
|
||||||
|
ReportManager().DisableReports(request->type, request->thread);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PPPManager::ControlInterface(interface_id ID, uint32 op, void *data, size_t length)
|
PPPManager::ControlInterface(interface_id ID, uint32 op, void *data, size_t length)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
|
interface_entry *entry = EntryFor(ID);
|
||||||
|
if(entry && !entry->deleting)
|
||||||
|
return entry->interface->Control(op, data, length);
|
||||||
|
|
||||||
|
return B_BAD_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -166,30 +390,111 @@ int32
|
|||||||
PPPManager::GetInterfaces(interface_id *interfaces, int32 count,
|
PPPManager::GetInterfaces(interface_id *interfaces, int32 count,
|
||||||
ppp_interface_filter filter = PPP_REGISTERED_INTERFACES)
|
ppp_interface_filter filter = PPP_REGISTERED_INTERFACES)
|
||||||
{
|
{
|
||||||
return 0;
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
|
int32 item = 0;
|
||||||
|
// the current item in 'interfaces' (also the number of ids copied)
|
||||||
|
interface_entry *entry;
|
||||||
|
|
||||||
|
for(int32 index = 0; item < count && index < fEntries.CountItems(); index++) {
|
||||||
|
entry = fEntries.ItemAt(index);
|
||||||
|
if(!entry || entry->deleting)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(filter) {
|
||||||
|
case PPP_ALL_INTERFACES:
|
||||||
|
interfaces[item++] = entry->interface->ID();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPP_REGISTERED_INTERFACES:
|
||||||
|
if(entry->interface->Ifnet())
|
||||||
|
interfaces[item++] = entry->interface->ID();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPP_UNREGISTERED_INTERFACES:
|
||||||
|
if(!entry->interface->Ifnet())
|
||||||
|
interfaces[item++] = entry->interface->ID();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
// the filter is unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
PPPManager::CountInterfaces(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES)
|
PPPManager::CountInterfaces(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES)
|
||||||
{
|
{
|
||||||
return 0;
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
|
if(filter == PPP_ALL_INTERFACES)
|
||||||
|
return fEntries.CountItems();
|
||||||
|
|
||||||
|
int32 count = 0;
|
||||||
|
interface_entry *entry;
|
||||||
|
|
||||||
|
for(int32 index = 0; index < fEntries.CountItems(); index++) {
|
||||||
|
entry = fEntries.ItemAt(index);
|
||||||
|
if(!entry || entry->deleting)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(filter) {
|
||||||
|
case PPP_REGISTERED_INTERFACES:
|
||||||
|
if(entry->interface->Ifnet())
|
||||||
|
++count;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PPP_UNREGISTERED_INTERFACES:
|
||||||
|
if(!entry->interface->Ifnet())
|
||||||
|
++count;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
// the filter is unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface_entry*
|
interface_entry*
|
||||||
PPPManager::EntryFor(interface_id ID, int32 *start = NULL) const
|
PPPManager::EntryFor(interface_id ID, int32 *saveIndex = NULL) const
|
||||||
{
|
{
|
||||||
if(ID == PPP_UNDEFINED_INTERFACE_ID)
|
if(ID == PPP_UNDEFINED_INTERFACE_ID)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
interface_entry *entry;
|
interface_entry *entry;
|
||||||
|
for(int32 index = 0; index < fEntries.CountItems(); index++) {
|
||||||
for(int32 index = start ? *start : 0; index < fEntries.CountItems(); index++) {
|
|
||||||
entry = fEntries.ItemAt(index);
|
entry = fEntries.ItemAt(index);
|
||||||
if(entry && entry->interface->ID() == ID) {
|
if(entry && entry->interface->ID() == ID) {
|
||||||
if(start)
|
if(saveIndex)
|
||||||
*start = index;
|
*saveIndex = index;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface_entry*
|
||||||
|
PPPManager::EntryFor(ifnet *ifp, int32 *saveIndex = NULL) const
|
||||||
|
{
|
||||||
|
if(!ifp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
interface_entry *entry;
|
||||||
|
for(int32 index = 0; index < fEntries.CountItems(); index++) {
|
||||||
|
entry = fEntries.ItemAt(index);
|
||||||
|
if(entry && entry->interface->Ifnet() == ifp) {
|
||||||
|
if(saveIndex)
|
||||||
|
*saveIndex = index;
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,3 +538,42 @@ PPPManager::FindUnit() const
|
|||||||
|
|
||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PPPManager::DeleterThreadEvent()
|
||||||
|
{
|
||||||
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
|
// delete and remove marked interfaces
|
||||||
|
interface_entry *entry;
|
||||||
|
for(int32 index = 0; index < fEntries.CountItems(); index++) {
|
||||||
|
entry = fEntries.ItemAt(index);
|
||||||
|
if(!entry) {
|
||||||
|
fEntries.RemoveItem(index);
|
||||||
|
--index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(entry->deleting && entry->accessing == 0) {
|
||||||
|
delete entry->interface;
|
||||||
|
delete entry;
|
||||||
|
fEntries.RemoveItem(index);
|
||||||
|
--index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PPPManager::Pulse()
|
||||||
|
{
|
||||||
|
LockerHelper locker(fLock);
|
||||||
|
|
||||||
|
interface_entry *entry;
|
||||||
|
for(int32 index = 0; index < fEntries.CountItems(); index++) {
|
||||||
|
entry = fEntries.ItemAt(index);
|
||||||
|
if(entry)
|
||||||
|
entry->interface->Pulse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,14 @@
|
|||||||
|
|
||||||
#include <KPPPInterface.h>
|
#include <KPPPInterface.h>
|
||||||
#include <KPPPManager.h>
|
#include <KPPPManager.h>
|
||||||
|
#include <core_funcs.h>
|
||||||
|
|
||||||
|
|
||||||
|
// these functions are defined in ppp.cpp
|
||||||
|
extern int ppp_ifnet_stop(ifnet *ifp);
|
||||||
|
extern int ppp_ifnet_output(ifnet *ifp, struct mbuf *buf, struct sockaddr *dst,
|
||||||
|
struct rtentry *rt0);
|
||||||
|
extern int ppp_ifnet_ioctl(ifnet *ifp, ulong cmd, caddr_t data);
|
||||||
|
|
||||||
|
|
||||||
typedef struct interface_entry {
|
typedef struct interface_entry {
|
||||||
@@ -24,8 +32,13 @@ class PPPManager {
|
|||||||
PPPManager();
|
PPPManager();
|
||||||
~PPPManager();
|
~PPPManager();
|
||||||
|
|
||||||
|
int32 Stop(ifnet *ifp);
|
||||||
|
int32 Output(ifnet *ifp, struct mbuf *buf, struct sockaddr *dst,
|
||||||
|
struct rtentry *rt0);
|
||||||
|
int32 Control(ifnet *ifp, ulong cmd, caddr_t data);
|
||||||
|
|
||||||
interface_id CreateInterface(const driver_settings *settings,
|
interface_id CreateInterface(const driver_settings *settings,
|
||||||
interface_id parentID);
|
interface_id parentID = PPP_UNDEFINED_INTERFACE_ID);
|
||||||
void DeleteInterface(interface_id ID);
|
void DeleteInterface(interface_id ID);
|
||||||
void RemoveInterface(interface_id ID);
|
void RemoveInterface(interface_id ID);
|
||||||
|
|
||||||
@@ -46,19 +59,25 @@ class PPPManager {
|
|||||||
{ 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)
|
||||||
|
|
||||||
interface_entry *EntryFor(interface_id ID, int32 *start = NULL) const;
|
interface_entry *EntryFor(interface_id ID, int32 *saveIndex = NULL) const;
|
||||||
|
interface_entry *EntryFor(ifnet *ifp, int32 *saveIndex = NULL) const;
|
||||||
|
|
||||||
interface_id NextID()
|
interface_id NextID()
|
||||||
{ return (interface_id) atomic_add((vint32*) &fNextID, 1); }
|
{ return (interface_id) atomic_add((vint32*) &fNextID, 1); }
|
||||||
|
|
||||||
|
void DeleterThreadEvent();
|
||||||
|
void Pulse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32 FindUnit() const;
|
int32 FindUnit() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BLocker fLock;
|
BLocker fLock, fReportLock;
|
||||||
PPPReportManager fReportManager;
|
PPPReportManager fReportManager;
|
||||||
List<interface_entry*> fEntries;
|
List<interface_entry*> fEntries;
|
||||||
interface_id fNextID;
|
interface_id fNextID;
|
||||||
|
thread_id fDeleterThread;
|
||||||
|
net_timer_id fPulseTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,37 @@ struct core_module_info *core = NULL;
|
|||||||
static PPPManager *manager = NULL;
|
static PPPManager *manager = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
ppp_ifnet_stop(ifnet *ifp)
|
||||||
|
{
|
||||||
|
if(manager)
|
||||||
|
return manager->Stop(ifp);
|
||||||
|
else
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
ppp_ifnet_output(ifnet *ifp, struct mbuf *buf, struct sockaddr *dst,
|
||||||
|
struct rtentry *rt0)
|
||||||
|
{
|
||||||
|
if(manager)
|
||||||
|
return manager->Output(ifp, buf, dst, rt0);
|
||||||
|
else
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
ppp_ifnet_ioctl(ifnet *ifp, ulong cmd, caddr_t data)
|
||||||
|
{
|
||||||
|
if(manager)
|
||||||
|
return manager->Control(ifp, cmd, data);
|
||||||
|
else
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
ppp_start(void *cpp)
|
ppp_start(void *cpp)
|
||||||
@@ -39,6 +70,7 @@ int
|
|||||||
ppp_stop()
|
ppp_stop()
|
||||||
{
|
{
|
||||||
delete manager;
|
delete manager;
|
||||||
|
manager = NULL;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user