Files

69 lines
2.4 KiB
C

// Network stack registry. This file owns the single active stack provider binding.
#include <stdint.h>
#include <stddef.h>
#include <ntlite/ddi/net_stack.h>
#include <ntlite/ddi/net_device.h>
#include <kernel/ke_debug.h>
#include <kernel/ke_spinlock.h>
#include <ntlite/ddi/io_driver.h>
static const NET_STACK_PROVIDER* gNetStackProvider = 0;
static SPINLOCK gNetStackLock = SPINLOCK_INIT;
// Implements the net Validate Stack Provider operation.
static KSTATUS NetValidateStackProvider(const NET_STACK_PROVIDER* p) {
if (!p || p->Version != NET_STACK_PROVIDER_VERSION || !p->Name)
return NTLSTATUS_INVALID_PARAMETER;
if (!p->StackDevice || !p->AttachDevice || !p->ReceiveFrame)
return NTLSTATUS_INVALID_PARAMETER;
if (!p->StackDevice->DriverObject ||
!p->StackDevice->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL])
return NTLSTATUS_INVALID_PARAMETER;
return NTLSTATUS_SUCCESS;
}
// Implements the net Register Stack Provider operation.
__declspec(dllexport) KSTATUS NetRegisterStackProvider(const NET_STACK_PROVIDER* provider) {
KSTATUS st = NetValidateStackProvider(provider);
if (!KSUCCESS(st))
return st;
uintptr_t flags = KeAcquireSpinlock(&gNetStackLock);
if (gNetStackProvider) {
KeReleaseSpinlock(&gNetStackLock, flags);
return NTLSTATUS_ALREADY_EXISTS;
}
gNetStackProvider = provider;
KeReleaseSpinlock(&gNetStackLock, flags);
DbgPrint("NET: registered stack provider %s\n", provider->Name);
// Stack drivers usually load before NIC drivers, but support the other
// order so driver.ini remains simple while the loader is still flat.
uint32_t count = NetGetDeviceCount();
for (uint32_t i = 0; i < count; ++i) {
NET_DEVICE* dev = NetGetDevice(i);
if (!dev)
continue;
KSTATUS attach = provider->AttachDevice(dev);
if (!KSUCCESS(attach)) {
DbgPrint("NET: provider %s attach for %s failed: 0x%x\n",
provider->Name, dev->Name, attach);
}
}
return NTLSTATUS_SUCCESS;
}
// Implements the net Get Stack Provider operation.
__declspec(dllexport) const NET_STACK_PROVIDER* NetGetStackProvider(void) {
uintptr_t flags = KeAcquireSpinlock(&gNetStackLock);
const NET_STACK_PROVIDER* p = gNetStackProvider;
KeReleaseSpinlock(&gNetStackLock, flags);
return p;
}