implement generic I/O async request object to replace file-specific async requests, refactor lwIP network stack to dispatch requests through IRPs with cancellation support, add cancellation polling to lwIP accept and receive operations using LwipSocketWaitRecvNetbuf and LwipSocketWaitAccept, introduce NetSubmitSocketIrp for routing socket operations via device IRPs, track network IRP statistics with SYS_NET_IRP_STATS, add process module lock spinlock and reference counting for process modules, implement dynamic module loading and unloading via user module handles, add POSIX dynamic loader APIs including dlopen, dlsym, dlerror, and dlclose, introduce PosixStart entry point for posix applications, add new native smoke tests for net IRPs.
This commit is contained in:
1 parent
ed3d065abd
commit
1f5477cf66
32 files changed
+3713
-551
No files matched your search
@@ -4,7 +4,8 @@
|
||||
// net_stack.h - provider interface between kernel socket facade and network stack drivers.
|
||||
|
||||
// The kernel owns process handles, user-memory copying, NET_DEVICE registration,
|
||||
// and SOCKET_OBJECT lifetime. A stack driver owns protocol implementation.
|
||||
// and SOCKET_OBJECT lifetime. A stack driver owns protocol implementation behind
|
||||
// a DEVICE_OBJECT so socket operations enter the same IRP pipe as other I/O.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
@@ -12,39 +13,165 @@
|
||||
#include <ntlite/ddi/net_device.h>
|
||||
#include <ntlite/ddi/net_abi.h>
|
||||
|
||||
#define NET_STACK_PROVIDER_VERSION 1u
|
||||
struct DEVICE_OBJECT;
|
||||
|
||||
#define NET_STACK_PROVIDER_VERSION 2u
|
||||
#define NET_IOCTL_SOCKET 0x4E455401u
|
||||
|
||||
typedef enum NET_SOCKET_IRP_OPERATION {
|
||||
NetSocketIrpInvalid = 0,
|
||||
NetSocketIrpCreate = 1,
|
||||
NetSocketIrpClose = 2,
|
||||
NetSocketIrpBind = 3,
|
||||
NetSocketIrpListen = 4,
|
||||
NetSocketIrpAccept = 5,
|
||||
NetSocketIrpConnect = 6,
|
||||
NetSocketIrpSend = 7,
|
||||
NetSocketIrpReceive = 8,
|
||||
NetSocketIrpSendTo = 9,
|
||||
NetSocketIrpReceiveFrom = 10,
|
||||
NetSocketIrpShutdown = 11,
|
||||
NetSocketIrpSetOption = 12,
|
||||
NetSocketIrpGetOption = 13,
|
||||
NetSocketIrpPoll = 14,
|
||||
NetSocketIrpResolveHost = 15,
|
||||
NetSocketIrpOperationCount,
|
||||
} NET_SOCKET_IRP_OPERATION;
|
||||
|
||||
typedef struct NET_SOCKET_IRP_REQUEST {
|
||||
uint32_t Size;
|
||||
uint32_t Operation;
|
||||
volatile uint8_t* CancelRequested;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint32_t Domain;
|
||||
uint32_t Type;
|
||||
uint32_t Protocol;
|
||||
void** ProviderSocketOut;
|
||||
} Create;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
} Close;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
const SYS_SOCKET_ADDRESS_K* Address;
|
||||
size_t AddressSize;
|
||||
} Bind;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
uint32_t Backlog;
|
||||
} Listen;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
void** AcceptedOut;
|
||||
SYS_SOCKET_ADDRESS_K* RemoteOut;
|
||||
} Accept;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
const SYS_SOCKET_ADDRESS_K* Address;
|
||||
size_t AddressSize;
|
||||
} Connect;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
const void* Buffer;
|
||||
size_t Length;
|
||||
uint32_t Flags;
|
||||
size_t* SentOut;
|
||||
} Send;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
void* Buffer;
|
||||
size_t Length;
|
||||
uint32_t Flags;
|
||||
size_t* ReceivedOut;
|
||||
} Receive;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
const void* Buffer;
|
||||
size_t Length;
|
||||
uint32_t Flags;
|
||||
const SYS_SOCKET_ADDRESS_K* Remote;
|
||||
size_t RemoteSize;
|
||||
size_t* SentOut;
|
||||
} SendTo;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
void* Buffer;
|
||||
size_t Length;
|
||||
uint32_t Flags;
|
||||
SYS_SOCKET_ADDRESS_K* RemoteOut;
|
||||
size_t* ReceivedOut;
|
||||
} ReceiveFrom;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
uint32_t How;
|
||||
} Shutdown;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
uint32_t Option;
|
||||
const void* Value;
|
||||
size_t ValueSize;
|
||||
} SetOption;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
uint32_t Option;
|
||||
void* Value;
|
||||
size_t ValueSize;
|
||||
size_t* ActualSizeOut;
|
||||
} GetOption;
|
||||
|
||||
struct {
|
||||
void* Socket;
|
||||
uint32_t Events;
|
||||
uint32_t* ReturnedEventsOut;
|
||||
} Poll;
|
||||
|
||||
struct {
|
||||
const char* Name;
|
||||
uint32_t Family;
|
||||
SYS_SOCKET_ADDRESS_K* AddressOut;
|
||||
} ResolveHost;
|
||||
} u;
|
||||
} NET_SOCKET_IRP_REQUEST;
|
||||
|
||||
typedef struct NET_IRP_STATS {
|
||||
uint64_t Submitted;
|
||||
uint64_t Completed;
|
||||
uint64_t CompletedSynchronously;
|
||||
uint64_t CompletedAsynchronously;
|
||||
uint64_t Pending;
|
||||
uint64_t CancelRequested;
|
||||
uint64_t Cancelled;
|
||||
uint64_t WouldBlock;
|
||||
uint64_t Timeout;
|
||||
uint64_t Failed;
|
||||
uint64_t ByOperation[NetSocketIrpOperationCount];
|
||||
} NET_IRP_STATS;
|
||||
|
||||
typedef struct NET_STACK_PROVIDER NET_STACK_PROVIDER;
|
||||
|
||||
struct NET_STACK_PROVIDER {
|
||||
uint32_t Version;
|
||||
const char* Name;
|
||||
struct DEVICE_OBJECT* StackDevice;
|
||||
|
||||
KSTATUS (*AttachDevice)(NET_DEVICE* device);
|
||||
KSTATUS (*ReceiveFrame)(NET_DEVICE* device, const void* frame, size_t length);
|
||||
|
||||
KSTATUS (*SocketCreate)(uint32_t domain, uint32_t type, uint32_t protocol, void** outSocket);
|
||||
void (*SocketClose)(void* socket);
|
||||
|
||||
KSTATUS (*Bind)(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize);
|
||||
KSTATUS (*Listen)(void* socket, uint32_t backlog);
|
||||
KSTATUS (*Accept)(void* socket, void** acceptedOut, SYS_SOCKET_ADDRESS_K* remoteOut);
|
||||
KSTATUS (*Connect)(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize);
|
||||
|
||||
KSTATUS (*Send)(void* socket, const void* buffer, size_t length, uint32_t flags, size_t* sentOut);
|
||||
KSTATUS (*Receive)(void* socket, void* buffer, size_t length, uint32_t flags, size_t* receivedOut);
|
||||
KSTATUS (*SendTo)(void* socket, const void* buffer, size_t length, uint32_t flags,
|
||||
const SYS_SOCKET_ADDRESS_K* remote, size_t remoteSize, size_t* sentOut);
|
||||
KSTATUS (*ReceiveFrom)(void* socket, void* buffer, size_t length, uint32_t flags,
|
||||
SYS_SOCKET_ADDRESS_K* remoteOut, size_t* receivedOut);
|
||||
|
||||
KSTATUS (*Shutdown)(void* socket, uint32_t how);
|
||||
KSTATUS (*SetOption)(void* socket, uint32_t option, const void* value, size_t valueSize);
|
||||
KSTATUS (*GetOption)(void* socket, uint32_t option, void* value, size_t valueSize, size_t* actualSizeOut);
|
||||
KSTATUS (*Poll)(void* socket, uint32_t events, uint32_t* returnedEventsOut);
|
||||
|
||||
KSTATUS (*ResolveHost)(const char* name, uint32_t family, SYS_SOCKET_ADDRESS_K* addressOut);
|
||||
};
|
||||
|
||||
__declspec(dllexport) KSTATUS NetRegisterStackProvider(const NET_STACK_PROVIDER* provider);
|
||||
__declspec(dllexport) const NET_STACK_PROVIDER* NetGetStackProvider(void);
|
||||
__declspec(dllexport) void NetQueryIrpStats(NET_IRP_STATS* out);
|
||||
@@ -431,6 +431,8 @@ typedef struct SYS_PROCESS_INFO {
|
||||
|
||||
uint32_t ThreadCount;
|
||||
uint32_t HandleCount;
|
||||
// ModuleCount is the number of DLL-like process modules recorded by the loader.
|
||||
// The main executable image is reported separately through ImageBase/ImageSize.
|
||||
uint32_t ModuleCount;
|
||||
uint32_t CurrentDrive;
|
||||
|
||||
@@ -452,6 +454,54 @@ uint32_t SysGetProcessList(SYS_PROCESS_INFO* processesOut, size_t maxCount, size
|
||||
uint32_t SysGetProcessPid(uint32_t handle, uint32_t* pidOut);
|
||||
uint32_t SysGetThreadList(uint32_t pid, SYS_THREAD_INFO* threadsOut, size_t maxCount, size_t* countOut);
|
||||
|
||||
#define SYS_MODULE_NAME_MAX 64u
|
||||
#define SYS_MODULE_INFO_VERSION 1u
|
||||
|
||||
#define SYS_LOAD_MODULE_FLAG_NONE 0u
|
||||
|
||||
#define SYS_MODULE_FLAG_PUBLIC_REF 0x00000001u
|
||||
#define SYS_MODULE_FLAG_IMPORT_PINNED 0x00000002u
|
||||
#define SYS_MODULE_FLAG_UNLOADABLE 0x00000004u
|
||||
|
||||
typedef struct SYS_MODULE_INFO {
|
||||
uint32_t Size;
|
||||
uint32_t Version;
|
||||
uint32_t Flags;
|
||||
uint32_t Reserved;
|
||||
|
||||
uintptr_t Base;
|
||||
size_t ImageSize;
|
||||
uintptr_t EntryPoint;
|
||||
|
||||
uint32_t PublicRefCount;
|
||||
uint32_t ImportRefCount;
|
||||
uint32_t TotalRefCount;
|
||||
uint32_t Reserved2;
|
||||
|
||||
char Name[SYS_MODULE_NAME_MAX];
|
||||
} SYS_MODULE_INFO;
|
||||
|
||||
typedef struct SYS_LOAD_MODULE_REQUEST {
|
||||
uint32_t Size;
|
||||
uint32_t Flags;
|
||||
SYS_STRING_VIEW Path;
|
||||
uint32_t* ModuleHandleOut;
|
||||
SYS_MODULE_INFO* InfoOut;
|
||||
} SYS_LOAD_MODULE_REQUEST;
|
||||
|
||||
typedef struct SYS_GET_MODULE_EXPORT_REQUEST {
|
||||
uint32_t Size;
|
||||
uint32_t ModuleHandle;
|
||||
SYS_STRING_VIEW Name;
|
||||
uintptr_t* AddressOut;
|
||||
} SYS_GET_MODULE_EXPORT_REQUEST;
|
||||
|
||||
uint32_t SysLoadModule(const SYS_LOAD_MODULE_REQUEST* request);
|
||||
uint32_t SysUnloadModule(uint32_t moduleHandle);
|
||||
uint32_t SysGetModuleInfo(uint32_t moduleHandle, SYS_MODULE_INFO* infoOut);
|
||||
uint32_t SysGetModuleExport(const SYS_GET_MODULE_EXPORT_REQUEST* request);
|
||||
uint32_t SysGetModuleList(SYS_MODULE_INFO* modulesOut, size_t maxCount, size_t* countOut);
|
||||
|
||||
uint32_t SysCreateThread(const SYS_CREATE_THREAD_REQUEST* request);
|
||||
uint32_t SysGetCurrentTid(void);
|
||||
uint32_t SysGetCurrentPid(void);
|
||||
@@ -722,6 +772,60 @@ typedef struct SYS_POLLFD {
|
||||
uint32_t ReturnedEvents;
|
||||
} SYS_POLLFD;
|
||||
|
||||
#define SYS_ASYNC_SOCKET_FLAG_NONE 0x00000000u
|
||||
|
||||
#define SYS_ASYNC_SOCKET_OP_BIND 1u
|
||||
#define SYS_ASYNC_SOCKET_OP_LISTEN 2u
|
||||
#define SYS_ASYNC_SOCKET_OP_ACCEPT 3u
|
||||
#define SYS_ASYNC_SOCKET_OP_CONNECT 4u
|
||||
#define SYS_ASYNC_SOCKET_OP_SEND 5u
|
||||
#define SYS_ASYNC_SOCKET_OP_RECV 6u
|
||||
#define SYS_ASYNC_SOCKET_OP_SEND_TO 7u
|
||||
#define SYS_ASYNC_SOCKET_OP_RECV_FROM 8u
|
||||
#define SYS_ASYNC_SOCKET_OP_SHUTDOWN 9u
|
||||
#define SYS_ASYNC_SOCKET_OP_SET_OPT 10u
|
||||
#define SYS_ASYNC_SOCKET_OP_GET_OPT 11u
|
||||
#define SYS_ASYNC_SOCKET_OP_POLL 12u
|
||||
|
||||
// Async socket requests return operation-specific byte counts through Iosb.
|
||||
// Information is the byte count for send/receive, the accepted handle for
|
||||
// accept, returned poll events for poll, and the actual option byte count for
|
||||
// get-option. RequestHandleOut receives a waitable/cancellable async I/O handle
|
||||
// when the request is queued. A zero handle means the operation failed before
|
||||
// queueing.
|
||||
typedef struct SYS_ASYNC_SOCKET_REQUEST {
|
||||
uint32_t Size;
|
||||
uint32_t SocketHandle;
|
||||
uint32_t EventHandle;
|
||||
uint32_t Operation;
|
||||
uint32_t Flags;
|
||||
uint32_t SocketFlags;
|
||||
uint32_t Backlog;
|
||||
uint32_t ShutdownHow;
|
||||
uint32_t Option;
|
||||
uint32_t PollEvents;
|
||||
|
||||
void* Buffer;
|
||||
size_t Length;
|
||||
|
||||
const SYS_SOCKET_ADDRESS* Address;
|
||||
size_t AddressSize;
|
||||
SYS_SOCKET_ADDRESS* AddressOut;
|
||||
size_t* AddressSizeInOut;
|
||||
|
||||
void* OptionValue;
|
||||
size_t OptionValueSize;
|
||||
size_t* OptionActualSizeOut;
|
||||
|
||||
uint32_t* HandleOut;
|
||||
uint32_t* PollReturnedEventsOut;
|
||||
|
||||
SYS_IO_STATUS_BLOCK* Iosb;
|
||||
SYS_USER_APC_ROUTINE ApcRoutine;
|
||||
void* ApcContext;
|
||||
uint32_t* RequestHandleOut;
|
||||
} SYS_ASYNC_SOCKET_REQUEST;
|
||||
|
||||
uint32_t SysCreateSocket(uint32_t domain, uint32_t type, uint32_t protocol, uint32_t* handleOut);
|
||||
uint32_t SysBindSocket(uint32_t socket, const SYS_SOCKET_ADDRESS* address, size_t addressSize);
|
||||
uint32_t SysListenSocket(uint32_t socket, uint32_t backlog);
|
||||
@@ -736,6 +840,7 @@ uint32_t SysResolveHost(const SYS_RESOLVE_HOST_REQUEST* request);
|
||||
uint32_t SysSetSocketOption(uint32_t socket, const SYS_SOCKET_OPTION_REQUEST* request);
|
||||
uint32_t SysGetSocketOption(uint32_t socket, const SYS_SOCKET_OPTION_REQUEST* request);
|
||||
uint32_t SysPoll(SYS_POLLFD* fds, size_t count, uint32_t timeoutMs, size_t* readyOut);
|
||||
uint32_t SysSocketIoAsync(const SYS_ASYNC_SOCKET_REQUEST* request);
|
||||
|
||||
typedef struct SYS_MEMORY_STATUS {
|
||||
uint64_t FreePhysicalBytes;
|
||||
@@ -760,6 +865,7 @@ typedef struct SYS_MEMORY_STATUS {
|
||||
#define SYS_KERNEL_STATS_SURFACE 9u
|
||||
#define SYS_KERNEL_STATS_FILESYSTEM 10u
|
||||
#define SYS_KERNEL_STATS_DISK 11u
|
||||
#define SYS_KERNEL_STATS_NET_IRP 12u
|
||||
|
||||
// Public stats payloads start with Size and Version. Size is the byte count
|
||||
// returned for that payload, including any trailing records. Version describes
|
||||
@@ -1007,6 +1113,40 @@ typedef struct SYS_DISK_STATS {
|
||||
uint64_t MaxReadaheadSectors;
|
||||
} SYS_DISK_STATS;
|
||||
|
||||
#define SYS_NET_IRP_OPERATION_COUNT 16u
|
||||
#define SYS_NET_IRP_OP_INVALID 0u
|
||||
#define SYS_NET_IRP_OP_CREATE 1u
|
||||
#define SYS_NET_IRP_OP_CLOSE 2u
|
||||
#define SYS_NET_IRP_OP_BIND 3u
|
||||
#define SYS_NET_IRP_OP_LISTEN 4u
|
||||
#define SYS_NET_IRP_OP_ACCEPT 5u
|
||||
#define SYS_NET_IRP_OP_CONNECT 6u
|
||||
#define SYS_NET_IRP_OP_SEND 7u
|
||||
#define SYS_NET_IRP_OP_RECEIVE 8u
|
||||
#define SYS_NET_IRP_OP_SEND_TO 9u
|
||||
#define SYS_NET_IRP_OP_RECEIVE_FROM 10u
|
||||
#define SYS_NET_IRP_OP_SHUTDOWN 11u
|
||||
#define SYS_NET_IRP_OP_SET_OPTION 12u
|
||||
#define SYS_NET_IRP_OP_GET_OPTION 13u
|
||||
#define SYS_NET_IRP_OP_POLL 14u
|
||||
#define SYS_NET_IRP_OP_RESOLVE_HOST 15u
|
||||
|
||||
typedef struct SYS_NET_IRP_STATS {
|
||||
uint32_t Size;
|
||||
uint32_t Version;
|
||||
uint64_t Submitted;
|
||||
uint64_t Completed;
|
||||
uint64_t CompletedSynchronously;
|
||||
uint64_t CompletedAsynchronously;
|
||||
uint64_t Pending;
|
||||
uint64_t CancelRequested;
|
||||
uint64_t Cancelled;
|
||||
uint64_t WouldBlock;
|
||||
uint64_t Timeout;
|
||||
uint64_t Failed;
|
||||
uint64_t ByOperation[SYS_NET_IRP_OPERATION_COUNT];
|
||||
} SYS_NET_IRP_STATS;
|
||||
|
||||
typedef struct SYS_SWAP_STATS {
|
||||
uint32_t Size;
|
||||
uint32_t Version;
|
||||
|
||||
Reference in new issue
Block a user