// Network stack registry. This file owns the single active stack provider binding. #include #include #include #include #include #include #include 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; }