[NETIO] Implement an in-kernel BSD-style networking API driver

This patch adds the NETIO.SYS driver to ReactOS. NETIO.SYS
is part of Windows since NT6 (Vista).

The driver is not feature complete (meaning some functionality is
unimplemented) but does its job quite good for what it originally
was written for (which is getting WinDRBD working on
ReactOS/Windows Server 2003 SP2).

The driver re-uses parts of the AFD.SYS driver, namely those
functions that ease communitating with the transport device
interface (TDI). Other than that, following features are implemented
and should work:

 * TCP/IP networking: connect, listen, accept, read, write
 * UDP/IP networking: write

So in a nutshell TCP/IP support is completed, UDP support is
partially complete and ICMP support does not exist yet.
In particular the listen/accept mechanism allows one to write
kernel side TCP servers that one can connect to via the internet.

The netio driver is licensed under the MIT license, see the file
netio.c for more details.

Have fun with it :)

Signed-off-by: Johannes Khoshnazar-Thoma <[email protected]>
This commit is contained in:
Johannes Thoma
2025-11-21 21:08:03 +02:00
committed by Timo Kreuzer
parent c425244a36
commit b18a46e315
8 changed files with 1551 additions and 15 deletions
+1
View File
@@ -3,5 +3,6 @@ add_subdirectory(afd)
add_subdirectory(dd)
add_subdirectory(ndis)
add_subdirectory(ndisuio)
add_subdirectory(netio)
add_subdirectory(tcpip)
add_subdirectory(tdi)
+28
View File
@@ -0,0 +1,28 @@
spec2def(netio.sys netio.spec ADD_IMPORTLIB)
# NETIO.SYS is a NT 6 driver
remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600)
# Including AFD is needed by the TDI helpers.
# They have been part of AFD before.
include_directories(
BEFORE include
../afd/include
../tdihelpers/include
${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers)
list(APPEND SOURCE
netio.c
../tdihelpers/tdi.c
../tdihelpers/tdiconn.c
${CMAKE_CURRENT_BINARY_DIR}/netio.def)
add_library(netio MODULE ${SOURCE})
target_link_libraries(netio ${PSEH_LIB})
set_module_type(netio kernelmodedriver)
add_importlibs(netio ntoskrnl hal)
add_cd_file(TARGET netio DESTINATION reactos/system32/drivers FOR all)
add_registry_inf(netio_reg.inf)
File diff suppressed because it is too large Load Diff
+4
View File
@@ -0,0 +1,4 @@
@ stdcall WskCaptureProviderNPI(ptr long ptr)
@ stdcall WskDeregister(ptr)
@ stdcall WskRegister(ptr ptr)
@ stdcall WskReleaseProviderNPI(ptr)
+7
View File
@@ -0,0 +1,7 @@
; Netio driver
[AddReg]
HKLM,"SYSTEM\CurrentControlSet\Services\Netio","ErrorControl",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\Netio","Group",0x00000000,"TDI"
HKLM,"SYSTEM\CurrentControlSet\Services\Netio","ImagePath",0x00020000,"system32\drivers\netio.sys"
HKLM,"SYSTEM\CurrentControlSet\Services\Netio","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\Netio","Type",0x00010001,0x00000001
+5 -10
View File
@@ -19,10 +19,8 @@
#include <tdiinfo.h>
/* If you want to see the DPRINT() output in your debugger,
* remove the following line (or comment it out):
*/
#define NDEBUG 1
* remove the following line (or comment it out): */
#define NDEBUG
#include <reactos/debug.h>
static NTSTATUS TdiCall(
@@ -133,8 +131,7 @@ static NTSTATUS TdiOpenDevice(
DPRINT("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status);
ZwClose(*Handle);
} else {
DPRINT("Got handle (%p) Object (%p)\n",
*Handle, *Object);
DPRINT("Got handle (%p) Object (%p)\n", *Handle, *Object);
}
} else {
DPRINT("ZwCreateFile() failed with status (0x%X)\n", Status);
@@ -170,8 +167,7 @@ NTSTATUS TdiOpenAddressFile(
ULONG EaLength;
PTRANSPORT_ADDRESS Address;
DPRINT("Called. DeviceName (%wZ) Name (%p)\n",
DeviceName, Name);
DPRINT("Called. DeviceName (%wZ) Name (%p)\n", DeviceName, Name);
/* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
@@ -384,8 +380,7 @@ NTSTATUS TdiAssociateAddressFile(
KEVENT Event;
PIRP Irp;
DPRINT("Called. AddressHandle (%p) ConnectionObject (%p)\n",
AddressHandle, ConnectionObject);
DPRINT("Called. AddressHandle (%p) ConnectionObject (%p)\n", AddressHandle, ConnectionObject);
if (!ConnectionObject) {
DPRINT("Bad connection object.\n");
+3 -5
View File
@@ -16,10 +16,8 @@
#endif
/* If you want to see the DPRINT() output in your debugger,
* remove the following line (or comment it out):
*/
#define NDEBUG 1
* remove the following line (or comment it out) */
#define NDEBUG
#include <reactos/debug.h>
UINT TdiAddressSizeFromType( UINT AddressType ) {
@@ -50,7 +48,7 @@ UINT TaLengthOfAddress( PTA_ADDRESS Addr )
AddrLen += 2 * sizeof( USHORT );
DPRINT("AddrLen %x\n");
DPRINT("AddrLen %x\n", AddrLen);
return AddrLen;
}
+1
View File
@@ -404,6 +404,7 @@ union _DL_EUI48 {
DL_EI48 Ei48;
};
};
typedef union _DL_EUI48 DL_EUI48, *PDL_EUI48;
C_ASSERT(DL_ADDRESS_LENGTH_MAXIMUM >= sizeof(DL_EUI48));