TCP/IP 协议驱动 (tcpip.sys) 分析
目录
1. 概述
tcpip.sys 是 ReactOS 的网络协议驱动程序,实现了完整的 TCP/IP 协议栈。它位于 NT 执行体中的 Io 管理器 和 NDIS 库 之间,为上层用户态应用程序(通过 Winsock)和下层 NDIS 微型端口驱动提供通信服务。
1.1 设计思想
ReactOS 的 TCP/IP 协议栈采用双栈架构:
- ReactOS 原生 IP 协议栈 (
ip/目录):自己实现的 IPv4 网络层(IP、ARP、ICMP、路由转发)和传输层(TCP、UDP、Raw IP) - lwIP 协议栈 (
lwip/目录):集成了 lwIP 2.x 第三方轻量级 TCP/IP 协议栈,通过ip/lwip_glue/粘合层接入
其中 TCP/IP 协议栈的核心(TCP 传输层)直接从 Linux 内核 2.4.20 移植而来 ,完整保留了 Linux 内核的 struct sk_buff、struct sock、struct tcp_opt 等核心数据结构和 TCP 状态机逻辑。
1.2 双栈架构的设计原因
ReactOS 采用双栈架构而非单一栈,主要基于以下历史和技术考量:
1. 复用经过验证的 TCP 实现
TCP 协议的状态机极其复杂(11 个状态、状态转换、拥塞控制、RTT 估算、重传计时器等),从零实现不仅工作量大,而且容易引入难以发现的时序 bug。Linux 内核 2.4.20 的 TCP 实现已经过大量生产环境验证,将其移植到 ReactOS 可以快速获得一个健壮的 TCP 层,这是项目早期的务实选择。
2. 原生 IP 栈为 Windows TDI 框架而写
虽然 TCP 层移植自 Linux,但整个协议栈的运行环境是 Windows 内核(通过 TDI 接口与上层通信、通过 NDIS 接口与网卡驱动通信)。因此 IP 网络层(分片重组、路由转发)、ARP、ICMP、数据链路层(NDIS 协议驱动回调)等都是为 ReactOS 原生编写的,以无缝适配 Windows 驱动模型。Linux 的 net_device、neigh 等数据结构不能直接在 NDIS 环境下工作。
3. lwIP 补充协议覆盖面
lwIP 是一个轻量级、独立于操作系统的 TCP/IP 协议栈实现,提供了原生 IP 栈未覆盖或实现不完善的协议特性:
- IPv6 支持:原生栈主要面向 IPv4,lwIP 提供了完整的 IPv6 协议簇
- DHCP 客户端:自动获取 IP 地址配置
- DNS 解析:域名解析功能
- PPP/PPPoE:拨号网络支持
- TLS 上层:基于 altcp 的传输层安全抽象
将这些协议在原生栈中逐一实现需要大量开发工作,而 lwIP 以成熟的第三方库形式提供了开箱即用的方案。
4. 实际使用方式
在当前的 ReactOS 代码中,两个栈并非完全独立运行。通过 ip/lwip_glue/ 粘合层,部分协议功能可以借助 lwIP 实现的同时仍通过 TDI 暴露给上层应用。这种设计允许逐步将更多的协议处理从原生栈迁移到 lwIP,或者在特定场景下选择更合适的栈来处理特定类型的网络流量。
注:虽然工程结构上同时包含了两个 IP 栈的实现,但当前 ReactOS 系统实际运行时主要使用的是 ReactOS 原生 IP 协议栈,lwIP 栈处于可用但并非默认激活的状态。这种并存结构为未来的协议栈演进提供了灵活性。
1.3 架构总览
用户态 (Winsock)
| TDI (Transport Driver Interface) → DeviceIoControl
v
+------------------------------------------+
| tcpip.sys |
| |
| +--------+ +--------+ +------------+ |
| | TCP 设备| | UDP 设备| | RawIP 设备 | |
| +--------+ +--------+ +------------+ |
| |
| TDI 分发层 (dispatch.c) |
| TDI_CONNECT/TDI_SEND/TDI_RECEIVE/... |
| |
| +----------+ +----------+ +----------+ |
| | TCP 模块 | | UDP 模块 | | RawIP 模块| |
| | (Linux | +----------+ +----------+ |
| | 2.4.20 | +----------+ +----------+ |
| | 移植) | | ICMP 模块 | | Datagram | |
| +----------+ +----------+ +----------+ |
| |
| IP 网络层 (ip.c / receive.c / transmit.c) |
| 协议表分发、分片重组、路由转发 |
| |
| ARP / 邻居缓存 / 路由表 |
| |
| 数据链路层 - LAN (datalink/lan.c) |
| NDIS 协议驱动接口 |
+------------------------------------------+
| NdisSend / NdisRequest / ...
v
+------------------------------------------+
| NDIS 库 (ndis.sys) |
+------------------------------------------+
| MiniportXxx
v
+------------------------------------------+
| 微型端口驱动 (e1000.sys, etc.) |
+------------------------------------------+
2. 框架结构
2.1 模块组织
tcpip.sys 的源码位于 d:\reactos\drivers\network\tcpip\,组织结构如下:
2.1.1 驱动顶层 (tcpip/)
| 源文件 | 功能 |
|---|---|
main.c |
驱动入口点 DriverEntry,创建设备对象,初始化各子系统 |
dispatch.c |
TDI IRP 分发处理(TDI_SEND/RECEIVE/CONNECT/LISTEN 等) |
fileobjs.c |
地址文件、连接端点、控制通道的文件对象管理 |
info.c |
TDI 信息查询/设置(InfoTdiQueryInformationEx) |
ainfo.c |
地址信息查询 |
cinfo.c |
连接信息查询 |
iinfo.c |
接口信息查询 |
tinfo.c |
TCP 信息查询 |
ninfo.c |
NetBIOS 信息查询 |
buffer.c |
NDIS 数据包/缓冲区封装 |
lock.c |
锁/同步操作封装 |
wait.c |
等待/同步操作封装 |
proto.c |
协议号提取工具 |
2.1.2 IP 网络层 (ip/network/)
| 源文件 | 功能 |
|---|---|
ip.c |
IP 模块初始化、接口管理、协议表注册/分发 |
receive.c |
IP 数据报接收、分片重组(RFC 815 算法) |
transmit.c |
IP 数据报发送、分片处理 |
interface.c |
IP 接口管理(注册/注销/查找) |
address.c |
IP 地址管理(IPv4/IPv6) |
router.c |
路由表管理(创建/查找/删除路由) |
route.c |
路由缓存和转发决策 |
arp.c |
ARP 协议(发送/接收/缓存管理) |
neighbor.c |
邻居缓存(NCE - Neighbor Cache Entry) |
icmp.c |
ICMP 协议(回显请求/响应、错误报告) |
checksum.c |
IP/TCP/UDP 校验和计算(含 x86 汇编优化) |
loopback.c |
回环接口适配器 |
ports.c |
TCP/UDP 端口分配管理 |
routines.c |
辅助工具函数 |
2.1.3 传输层 (ip/transport/)
| 源文件 | 功能 |
|---|---|
tcp/tcp.c |
TCP 核心:连接管理、发送/接收窗口、重传计时器 |
tcp/accept.c |
TCP 监听/接受连接 |
tcp/event.c |
TCP 事件处理 |
tcp/if.c |
TCP 接口绑定/交互 |
udp/udp.c |
UDP 数据报发送/接收 |
rawip/rawip.c |
Raw IP 数据报发送/接收 |
datagram/datagram.c |
数据报通用基础设施(请求队列、完成回调) |
2.1.4 数据链路层 (datalink/)
| 源文件 | 功能 |
|---|---|
lan.c |
NDIS 协议注册、适配器绑定/解绑、ProtocolXxx 回调、数据包收发 |
2.1.5 lwIP 粘合层 (ip/lwip_glue/)
| 源文件 | 功能 |
|---|---|
ip.c |
lwIP IP 接口适配 |
memory.c |
lwIP 内存分配适配 |
sys_arch.c |
lwIP 系统层适配(线程/信号量/邮箱) |
tcp.c |
lwIP TCP 适配 |
2.1.6 辅助模块
| 源文件 | 功能 |
|---|---|
chew/workqueue.c |
工作队列(Chew - 异步任务调度) |
2.2 TDI 接口
tcpip.sys 通过 TDI (Transport Driver Interface) 向上层提供网络服务。TDI 定义了传输层驱动的标准接口,包括:
TDI 设备对象 (创建于 DriverEntry):
\Device\Tcp--- TCP 设备,提供面向连接的流服务\Device\Udp--- UDP 设备,提供无连接的数据报服务\Device\Ip--- IP 设备,提供原始 IP 服务\Device\RawIp--- Raw IP 设备,支持自定义协议号的原始套接字
TDI IRP Minor Function (定义在 dispatch.c):
| Minor Function | 处理函数 | 用途 |
|---|---|---|
TDI_CONNECT |
DispTdiConnect |
TCP 连接请求 |
TDI_LISTEN |
DispTdiListen |
TCP 监听请求 |
TDI_ACCEPT |
DispTdiAccept |
TCP 接受连接 |
TDI_DISCONNECT |
DispTdiDisconnect |
TCP 断开连接 |
TDI_SEND |
DispTdiSend |
TCP 数据发送 |
TDI_RECEIVE |
DispTdiReceive |
TCP 数据接收 |
TDI_SEND_DATAGRAM |
DispTdiSendDatagram |
UDP 数据报发送 |
TDI_RECEIVE_DATAGRAM |
DispTdiReceiveDatagram |
UDP 数据报接收 |
TDI_ASSOCIATE_ADDRESS |
DispTdiAssociateAddress |
关联地址和连接 |
TDI_DISASSOCIATE_ADDRESS |
DispTdiDisassociateAddress |
解除地址关联 |
TDI_SET_EVENT_HANDLER |
DispTdiSetEventHandler |
设置事件回调 |
TDI_QUERY_INFORMATION |
DispTdiQueryInformation |
查询连接/地址信息 |
TDI_SET_INFORMATION |
DispTdiSetInformation |
设置信息 |
TDI 事件类型 (通过 TDI_SET_EVENT_HANDLER 注册):
| 事件 | 用途 |
|---|---|
TDI_EVENT_CONNECT |
有新的连接到达 |
TDI_EVENT_DISCONNECT |
连接断开 |
TDI_EVENT_RECEIVE |
有数据可接收 |
TDI_EVENT_RECEIVE_DATAGRAM |
有数据报可接收 |
TDI_EVENT_RECEIVE_EXPEDITED |
有紧急数据可接收 |
TDI_EVENT_CHAINED_RECEIVE |
链式接收 |
TDI_EVENT_CHAINED_RECEIVE_DATAGRAM |
链式数据报接收 |
TDI_EVENT_ERROR |
错误通知 |
2.3 文件对象类型
tcpip.sys 定义了三种文件对象类型:
| 文件对象类型 | FsContext2 值 | 用途 |
|---|---|---|
| 地址文件 | TDI_TRANSPORT_ADDRESS_FILE |
绑定 IP 地址和端口(UDP/TCP 监听) |
| 连接文件 | TDI_CONNECTION_FILE |
TCP 连接端点(面向连接通信) |
| 控制通道 | TDI_CONTROL_CHANNEL_FILE |
控制操作(信息查询/设置) |
3. 核心数据结构
3.1 IP 数据包 (IP_PACKET)
定义在 ip.h(file:///d:/reactos/drivers/network/tcpip/include/ip.h#L77-L91):
c
typedef struct _IP_PACKET {
OBJECT_FREE_ROUTINE Free; // 释放资源的函数
UCHAR Type; // IP 地址类型 (IPv4/IPv6)
UCHAR Flags; // 标记位
BOOLEAN MappedHeader; // Header 是否来自 MDL 映射
BOOLEAN ReturnPacket; // 是否需调用 NdisReturnPackets
PVOID Header; // IP 头指针
UINT HeaderSize; // IP 头大小
PVOID Data; // 当前数据指针
UINT TotalSize; // 数据包总大小
UINT Position; // 当前逻辑偏移
PNDIS_PACKET NdisPacket; // 底层 NDIS 数据包
IP_ADDRESS SrcAddr; // 源地址
IP_ADDRESS DstAddr; // 目的地址
} IP_PACKET, *PIP_PACKET;
3.2 IP 接口 (IP_INTERFACE)
c
typedef struct _IP_INTERFACE {
LIST_ENTRY ListEntry; // 链表入口
KSPIN_LOCK Lock; // 自旋锁
PVOID Context; // 下层 (LAN) 上下文
UINT HeaderSize; // 链路层头大小 (如以太网 = 14)
UINT MinFrameSize; // 最小帧大小
UINT MTU; // 最大传输单元
UINT Speed; // 链路速度
UINT Metric; // 接口跃点数
IP_ADDRESS Unicast; // 单播地址
IP_ADDRESS PointToPoint; // 点对点地址
IP_ADDRESS Netmask; // 子网掩码
IP_ADDRESS Broadcast; // 广播地址
UNICODE_STRING Name; // 适配器名称 (GUID)
UNICODE_STRING Description; // 适配器描述
PUCHAR Address; // 物理地址
UINT AddressLength; // 物理地址长度
UINT Index; // 适配器索引
LL_TRANSMIT_ROUTINE Transmit; // 链路层发送函数
PVOID TCPContext; // TCP 上下文
SEND_RECV_STATS Stats; // 收发统计
} IP_INTERFACE, *PIP_INTERFACE;
3.3 地址文件 (ADDRESS_FILE)
定义在 titypes.h(file:///d:/reactos/drivers/network/tcpip/include/titypes.h#L112-L120):
c
typedef struct _ADDRESS_FILE {
LIST_ENTRY ListEntry;
LONG RefCount;
OBJECT_FREE_ROUTINE Free;
ERESOURCE Resource; // 线程资源锁
IP_ADDRESS Address; // 本地 IP 地址
USHORT Family; // 地址族
USHORT Protocol; // 协议号
USHORT Port; // 网络端口 (网络字节序)
DATAGRAM_SEND_ROUTINE Send; // 数据报发送函数
PCONNECTION_ENDPOINT Connection; // 关联的连接端点
PCONNECTION_ENDPOINT Listener; // TCP 监听器
// ... 各种事件处理器和注册标记
} ADDRESS_FILE, *PADDRESS_FILE;
3.4 连接端点 (CONNECTION_ENDPOINT)
这是 TCP 的核心数据结构,包含 Linux 内核 struct tcp_opt 的完整移植:
CONNECTION_ENDPOINT
├── 对象管理: RefCount, Free, Resource (ERESOURCE)
├── TCP 状态: State (LISTEN/SYN_SENT/ESTABLISHED/...)
├── 地址绑定: AddressFile, LocalAddress, RemoteAddress, LocalPort, RemotePort
├── TCP 选项/状态 (Linux struct tcp_opt 移植):
│ ├── 发送窗口: snd_una, snd_nxt, snd_wnd, snd_wl1/snd_wl2
│ ├── 接收窗口: rcv_nxt, rcv_wnd, rcv_wup
│ ├── 拥塞控制: ssthresh, cwnd
│ ├── RTT 估算: srtt, mdev, rto
│ └── 计时器管理: retransmit_timer, persist_timer, keepalive_timer, 2MSL_timer
├── 缓冲区队列:
│ ├── SendQueue/RecvQueue (PTDI_BUCKET)
│ ├── SendDataQueue (sk_buff 链表)
│ └── FastSendDataQueue
└── IRP 管理: RequestList, ConnectRequest, DisconnectRequest, SendRequest, ReceiveRequest
3.5 链路层适配器 (LAN_ADAPTER)
定义在 lan.h(file:///d:/reactos/drivers/network/tcpip/include/lan.h):
c
typedef struct _LAN_ADAPTER {
LIST_ENTRY ListEntry; // 适配器链表入口
KSPIN_LOCK Lock; // 自旋锁
NDIS_HANDLE NdisHandle; // NDIS 打开句柄
NDIS_STATUS NdisStatus; // 异步操作状态
KEVENT Event; // 同步事件
PIP_INTERFACE Context; // IP 接口指针
// 硬件信息
UCHAR HWAddress[IEEE_802_ADDR_LENGTH]; // MAC 地址
UINT HWAddressLength;
NDIS_MEDIUM Media; // 介质类型
UINT HeaderSize; // 链路层头大小
UINT MinFrameSize; // 最小帧大小
UINT MTU; // MTU 大小
UINT MaxSendPackets; // 最大发送包数
UINT MaxPacketSize; // 最大包大小
UINT Speed; // 链路速度
UINT PacketFilter; // 数据包过滤器
UINT MacOptions; // MAC 选项
LAN_STATE State; // 状态机
BOOLEAN CompletingReset; // 是否完成重置
LAN_STATE OldState; // 重置前状态
} LAN_ADAPTER, *PLAN_ADAPTER;
3.6 全局链表体系
全局地址文件列表 (AddressFileListHead)
├── ADDRESS_FILE (TCP:80) ←→ ADDRESS_FILE (UDP:53)
├── ...
全局连接端点列表 (ConnectionEndpointListHead)
├── CONNECTION_ENDPOINT (TCP ESTABLISHED)
├── CONNECTION_ENDPOINT (TCP LISTEN)
├── ...
全局接口列表 (InterfaceListHead)
├── IP_INTERFACE (e1000) ←→ IP_INTERFACE (loopback)
├── ...
包上下文链表 (PACKET_CONTEXT → DLComplete 回调链)
重装列表 (ReassemblyListHead) --- IP 分片重组
├── IPDATAGRAM_REASSEMBLY → HoleList + FragmentList
协议表 (ProtocolTable[256]) --- 按协议号分发 IP 数据
├── [IPPROTO_TCP=6] → TCPReceive
├── [IPPROTO_UDP=17] → UDPReceive
├── [IPPROTO_ICMP=1] → ICMPReceive
└── [IPPROTO_RAW=0] → RawIPReceive
4. 核心模块分析
4.1 驱动入口与初始化 (main.c)
DriverEntry 函数执行以下初始化步骤:
- 初始化 DPC 和计时器 :
IPTimeoutDpc用于 IP 超时处理(ARP 缓存过期、路由缓存清理等),每IP_TIMEOUT(1000ms) 触发一次 - 创建 4 个设备对象 :
\Device\Ip、\Device\RawIp、\Device\Udp、\Device\Tcp - 初始化工作队列 :
ChewInit创建异步工作队列 - 分配 NDIS 资源:500+1500 个数据包池、2000 个缓冲区描述符
- 初始化全局列表:地址文件列表、连接端点列表、接口列表
- 启动各子系统 :
IPStartup--- IP 网络层(初始化协议表、接口列表、重装列表、ARP 缓存)RawIPStartup--- Raw IP 传输层UDPStartup--- UDP 传输层TCPStartup--- TCP 传输层ICMPStartup--- ICMP 协议
- 初始化安全描述符
- 注册 IRP 分发函数 :
IRP_MJ_CREATE/CLOSE→TiDispatchOpenClose,IRP_MJ_INTERNAL_DEVICE_CONTROL→TiDispatchInternal,IRP_MJ_DEVICE_CONTROL→TiDispatch - 创建回环适配器 :
LoopRegisterAdapter - 注册 NDIS 协议 :
LANRegisterProtocol--- 通过 NDIS 绑定到所有微型端口
4.2 IRP 分发 (dispatch.c)
IRP 完成函数 IRPFinish:
- 如果状态不是
STATUS_PENDING,取消 IRP 的取消例程并完成请求(增加网络优先级IO_NETWORK_INCREMENT)
内部 IOCTL 分发 TiDispatchInternal:
处理所有 TDI Minor Function,包括:
TDI_CONNECT→DispTdiConnect→TCPConnect(异步,通过TCP_COMPLETION_ROUTINE回调)TDI_SEND→DispTdiSend→TCPSendDataTDI_RECEIVE→DispTdiReceive→TCPReceiveDataTDI_SEND_DATAGRAM→DispTdiSendDatagram→UDP/RawIP的Send函数TDI_RECEIVE_DATAGRAM→DispTdiReceiveDatagram→DGReceiveDatagramTDI_LISTEN→DispTdiListen→TCPListen+TCPAcceptTDI_SET_EVENT_HANDLER→DispTdiSetEventHandler→ 设置各类事件回调
设备 IOCTL 分发 TiDispatch:
IOCTL_TCP_QUERY_INFORMATION_EX--- TDI 扩展信息查询IOCTL_TCP_SET_INFORMATION_EX--- TDI 扩展信息设置IOCTL_SET_IP_ADDRESS--- 设置 IP 地址IOCTL_DELETE_IP_ADDRESS--- 删除 IP 地址IOCTL_QUERY_IP_HW_ADDRESS--- 查询硬件地址(通过 ARP)IOCTL_ICMP_ECHO_REQUEST--- ICMP ping 请求
4.3 IP 网络层
4.3.1 IP 接收 (receive.c)
IPReceive 函数处理从链路层传入的 IP 数据报:
- 验证 IP 头(版本、校验和、总长度)
- 检查是否是本机地址(单播/广播/多播)
- 分片处理 (RFC 815 算法):通过
ReassemblyListHead管理正在进行重装的 IP 数据报- 每个分片创建一个
IP_FRAGMENT结构 - 重组使用
IPDATAGRAM_REASSEMBLY+IPDATAGRAM_HOLE描述空洞 - 当所有片段到达后,组装完整数据报
- 每个分片创建一个
- 调用
IPDispatchProtocol按Protocol字段分发给 TCP/UDP/ICMP 处理函数
4.3.2 IP 发送 (transmit.c)
IPTransmitPacket 处理 IP 数据报发送:
- 路由查找:通过
RouteGetRouteToDestination查找目标路由 - MTU 分片 :如果数据报超过出接口 MTU,创建
IPFRAGMENT_CONTEXT进行分片- 每片包含 IP 头 + 数据片段
- 设置正确的 Fragment Offset 和 MF 标志
- 重新计算校验和
- 通过
NBQueuePacket将数据包放入邻居缓存发送队列
4.3.3 IP 协议表
IP 层维护一个 ProtocolTable[256] 的函数指针表,按协议号索引:
c
IP_PROTOCOL_HANDLER ProtocolTable[IP_PROTOCOL_TABLE_SIZE];
// 注册
IPRegisterProtocol(IPPROTO_TCP, TCPReceive);
IPRegisterProtocol(IPPROTO_UDP, UDPReceive);
IPRegisterProtocol(IPPROTO_ICMP, ICMPReceive);
// 调用
ProtocolTable[IPHeader->Protocol](Interface, IPPacket);
4.3.4 IP 接口管理 (interface.c)
IPRegisterInterface--- 将新接口加入全局InterfaceListHeadIPUnregisterInterface--- 从全局列表移除接口AddrLocateInterface--- 根据 IP 地址查找对应的接口IPCreateInterface--- 从LLIP_BIND_INFO创建接口
4.3.5 路由管理 (router.c / route.c)
RouterCreateRoute--- 添加路由(目标、掩码、下一跳、接口)RouterRemoveRoute/RouterRemoveRoutesForInterface--- 删除路由RouteGetRouteToDestination--- 查找最佳匹配路由IPAddInterfaceRoute/IPRemoveInterfaceRoute--- 接口直连路由管理
4.4 传输层
4.4.1 TCP 模块 (tcp.c / accept.c / event.c / if.c)
TCP 实现直接从 Linux 内核 2.4.20 移植(见 tcpcore.h(file:///d:/reactos/drivers/network/tcpip/include/tcpcore.h) 注释),保留了:
- 完整 TCP 状态机:CLOSED → LISTEN → SYN_SENT → SYN_RECEIVED → ESTABLISHED → FIN_WAIT_1/2 → CLOSE_WAIT → CLOSING → LAST_ACK → TIME_WAIT
- 拥塞控制:慢启动、拥塞避免、快速重传、快速恢复
- RTT 估算:SRTT、RTTVAR、RTO 计算
- 滑动窗口:发送窗口、接收窗口、窗口通告
- 计时器管理:重传计时器、坚持计时器、保活计时器、2MSL 计时器
关键函数:
| 函数 | 位置 | 功能 |
|---|---|---|
TCPSocket |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | 创建 TCP socket(初始化 Linux tcp_opt) |
TCPConnect |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | 发起 TCP 连接(发送 SYN) |
TCPListen |
accept.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c) | 进入监听状态 |
TCPAccept |
accept.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c) | 接受进入的连接 |
TCPReceiveData |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | 接收 TCP 数据 |
TCPSendData |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | 发送 TCP 数据 |
TCPDisconnect |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | 断开连接(发送 FIN/RST) |
HandleSignalledConnection |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | TCP 事件处理(数据到达/状态变更) |
4.4.2 UDP 模块 (udp.c)
UDP 实现相对简单:
UDPSend--- 构造 UDP 数据报并通过 IP 层发送UDPReceive--- 接收 IP 层传来的 UDP 数据报,查找对应的地址文件进行分发UDPStartup/UDPShutdown--- 初始化/清理- 端口管理通过
TCPAllocatePort/TCPFreePort与 TCP 共享端口空间
4.4.3 Raw IP 模块 (rawip.c)
RawIPSend--- 构造并发送原始 IP 数据报RawIPReceive--- 接收原始 IP 数据报- 支持自定义协议号的协议(通过文件对象名称中的数字指定)
4.4.4 ICMP 模块 (icmp.c)
ICMPReceive--- 处理 ICMP 回显请求(返回回显应答)和错误报告ICMPTransmit--- 发送 ICMP 错误报告(如目的不可达)ICMPEchoRequest--- 处理 ping 请求
4.5 数据链路层 (lan.c)
LAN 层是 tcpip.sys 与 NDIS 的直接接口,实现了 NDIS 协议驱动所需的所有回调:
4.5.1 NDIS 协议注册 (LANRegisterProtocol)
填充 NDIS_PROTOCOL_CHARACTERISTICS 并调用 NdisRegisterProtocol:
c
ProtChars.OpenAdapterCompleteHandler = ProtocolOpenAdapterComplete;
ProtChars.CloseAdapterCompleteHandler = ProtocolCloseAdapterComplete;
ProtChars.ResetCompleteHandler = ProtocolResetComplete;
ProtChars.RequestCompleteHandler = ProtocolRequestComplete;
ProtChars.SendCompleteHandler = ProtocolSendComplete;
ProtChars.TransferDataCompleteHandler = ProtocolTransferDataComplete;
ProtChars.ReceivePacketHandler = ProtocolReceivePacket;
ProtChars.ReceiveHandler = ProtocolReceive;
ProtChars.ReceiveCompleteHandler = ProtocolReceiveComplete;
ProtChars.StatusHandler = ProtocolStatus;
ProtChars.StatusCompleteHandler = ProtocolStatusComplete;
ProtChars.BindAdapterHandler = ProtocolBindAdapter;
ProtChars.PnPEventHandler = ProtocolPnPEvent;
ProtChars.UnbindAdapterHandler = ProtocolUnbindAdapter;
4.5.2 适配器注册 (LANRegisterAdapter)
- 分配
LAN_ADAPTER结构 - 调用
NdisOpenAdapter打开 NDIS 适配器 - 查询硬件地址、MTU、最大发送包数等
- 构建
LLIP_BIND_INFO并调用IPCreateInterface - 读取注册表 IP 配置(IP 地址、掩码、网关)
- 设置数据包过滤器以接收广播/单播/多播
- 更新 TCP 接口信息
4.5.3 数据包接收
LAN 层支持两种 NDIS 接收模式:
-
传统接收 (
ProtocolReceive):- 来自 NDIS
MiniIndicateData→ 调用NdisTransferData复制完整数据帧 - 完成后调用
LanReceiveWorker在工作队列中处理
- 来自 NDIS
-
数据包接收 (
ProtocolReceivePacket):- 来自 NDIS
MiniIndicateReceivePacket - 直接提交到工作队列,不复制数据
- 返回 1 表示持有包引用(可通过
NdisReturnPackets归还)
- 来自 NDIS
两种模式最终都在 LanReceiveWorker 中汇合:
- 解析以太网类型(
ETYPE_IPv4/ETYPE_IPv6/ETYPE_ARP) - 初始化
IP_PACKET结构 - 调用
IPReceive(IP 数据报)或ARPReceive(ARP 请求)
4.5.4 数据包发送 (LANTransmit)
- 将数据拷贝到带以太网头的 NDIS 数据包
- 填充以太网头(目的 MAC、源 MAC、协议类型)
- 对大包设置
TcpLargeSendPacketInfo(LSO 卸载指示) - 调用
NdisSend发送 - 如果不是
NDIS_STATUS_PENDING,立即调用ProtocolSendComplete
4.5.5 状态变化处理 (ProtocolStatus)
处理网络状态变化事件:
NDIS_STATUS_MEDIA_CONNECT→ 设置LAN_STATE_STARTED,重新配置接口NDIS_STATUS_MEDIA_DISCONNECT→ 设置LAN_STATE_STOPPED,清除 IP 配置NDIS_STATUS_RESET_START/NDIS_STATUS_RESET_END→ 适配器重置状态管理
4.6 工作队列 (chew/workqueue.c)
Chew 工作队列提供异步任务调度:
ChewInit--- 创建工作线程ChewCreate--- 提交工作任务- 用于接收处理、重配置等异步操作
4.7 ARP 和邻居缓存
ARP 模块 (arp.c) 和邻居缓存 (neighbor.c) 共同实现链路层地址解析:
- ARP 发送 (
ARPTransmit) --- 发送 ARP 请求/应答 - ARP 接收 (
ARPReceive) --- 处理 ARP 应答,更新 NCE - 邻居查找 (
NBLocateNeighbor) --- 查找 IP 对应的链路层地址 - 邻居缓存条目 (NCE) --- LRU 缓存,支持
NUD_INCOMPLETE/NUD_REACHABLE/NUD_STALE/NUD_DELAY/NUD_PROBE等状态 - 发送队列 (
NBQueuePacket) --- 当 NCE 状态为 INCOMPLETE 时,数据包先排队等待 ARP 完成
5. 工作流程图
5.1 驱动初始化流程
#mermaid-svg-mxvGN5EWFO4zDpwB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mxvGN5EWFO4zDpwB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mxvGN5EWFO4zDpwB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mxvGN5EWFO4zDpwB .error-icon{fill:#552222;}#mermaid-svg-mxvGN5EWFO4zDpwB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mxvGN5EWFO4zDpwB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mxvGN5EWFO4zDpwB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mxvGN5EWFO4zDpwB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mxvGN5EWFO4zDpwB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mxvGN5EWFO4zDpwB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mxvGN5EWFO4zDpwB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mxvGN5EWFO4zDpwB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mxvGN5EWFO4zDpwB .marker.cross{stroke:#333333;}#mermaid-svg-mxvGN5EWFO4zDpwB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mxvGN5EWFO4zDpwB p{margin:0;}#mermaid-svg-mxvGN5EWFO4zDpwB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mxvGN5EWFO4zDpwB .cluster-label text{fill:#333;}#mermaid-svg-mxvGN5EWFO4zDpwB .cluster-label span{color:#333;}#mermaid-svg-mxvGN5EWFO4zDpwB .cluster-label span p{background-color:transparent;}#mermaid-svg-mxvGN5EWFO4zDpwB .label text,#mermaid-svg-mxvGN5EWFO4zDpwB span{fill:#333;color:#333;}#mermaid-svg-mxvGN5EWFO4zDpwB .node rect,#mermaid-svg-mxvGN5EWFO4zDpwB .node circle,#mermaid-svg-mxvGN5EWFO4zDpwB .node ellipse,#mermaid-svg-mxvGN5EWFO4zDpwB .node polygon,#mermaid-svg-mxvGN5EWFO4zDpwB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mxvGN5EWFO4zDpwB .rough-node .label text,#mermaid-svg-mxvGN5EWFO4zDpwB .node .label text,#mermaid-svg-mxvGN5EWFO4zDpwB .image-shape .label,#mermaid-svg-mxvGN5EWFO4zDpwB .icon-shape .label{text-anchor:middle;}#mermaid-svg-mxvGN5EWFO4zDpwB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mxvGN5EWFO4zDpwB .rough-node .label,#mermaid-svg-mxvGN5EWFO4zDpwB .node .label,#mermaid-svg-mxvGN5EWFO4zDpwB .image-shape .label,#mermaid-svg-mxvGN5EWFO4zDpwB .icon-shape .label{text-align:center;}#mermaid-svg-mxvGN5EWFO4zDpwB .node.clickable{cursor:pointer;}#mermaid-svg-mxvGN5EWFO4zDpwB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mxvGN5EWFO4zDpwB .arrowheadPath{fill:#333333;}#mermaid-svg-mxvGN5EWFO4zDpwB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mxvGN5EWFO4zDpwB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mxvGN5EWFO4zDpwB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mxvGN5EWFO4zDpwB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mxvGN5EWFO4zDpwB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mxvGN5EWFO4zDpwB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mxvGN5EWFO4zDpwB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mxvGN5EWFO4zDpwB .cluster text{fill:#333;}#mermaid-svg-mxvGN5EWFO4zDpwB .cluster span{color:#333;}#mermaid-svg-mxvGN5EWFO4zDpwB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mxvGN5EWFO4zDpwB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mxvGN5EWFO4zDpwB rect.text{fill:none;stroke-width:0;}#mermaid-svg-mxvGN5EWFO4zDpwB .icon-shape,#mermaid-svg-mxvGN5EWFO4zDpwB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mxvGN5EWFO4zDpwB .icon-shape p,#mermaid-svg-mxvGN5EWFO4zDpwB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mxvGN5EWFO4zDpwB .icon-shape .label rect,#mermaid-svg-mxvGN5EWFO4zDpwB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mxvGN5EWFO4zDpwB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mxvGN5EWFO4zDpwB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mxvGN5EWFO4zDpwB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} NDIS 协议绑定
DriverEntry
初始化 DPC 和计时器
创建 4 个设备对象: IP/RawIP/UDP/TCP
ChewInit 创建工作队列
分配 NDIS 数据包池和缓冲区池
初始化全局列表
IPStartup - 网络层
RawIPStartup - 传输层
UDPStartup - 传输层
TCPStartup - 传输层
ICMPStartup - ICMP
初始化安全描述符
注册 IRP 分发表
LoopRegisterAdapter 创建回环
LANRegisterProtocol 注册 NDIS
NDIS 调用 ProtocolBindAdapter
NDIS 枚举所有微型端口
ProtocolBindAdapter → LANRegisterAdapter
NdisOpenAdapter 打开适配器
查询硬件信息
读取注册表 IP 配置
IPCreateInterface 创建接口
IPRegisterInterface 注册接口
设置数据包过滤器
启动周期计时器
系统就绪
5.2 TCP 连接建立流程 (TDI_CONNECT)
#mermaid-svg-oy8TaCzMJXYQVfyG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-oy8TaCzMJXYQVfyG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-oy8TaCzMJXYQVfyG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-oy8TaCzMJXYQVfyG .error-icon{fill:#552222;}#mermaid-svg-oy8TaCzMJXYQVfyG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oy8TaCzMJXYQVfyG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-oy8TaCzMJXYQVfyG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oy8TaCzMJXYQVfyG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oy8TaCzMJXYQVfyG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-oy8TaCzMJXYQVfyG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oy8TaCzMJXYQVfyG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oy8TaCzMJXYQVfyG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oy8TaCzMJXYQVfyG .marker.cross{stroke:#333333;}#mermaid-svg-oy8TaCzMJXYQVfyG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oy8TaCzMJXYQVfyG p{margin:0;}#mermaid-svg-oy8TaCzMJXYQVfyG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-oy8TaCzMJXYQVfyG .cluster-label text{fill:#333;}#mermaid-svg-oy8TaCzMJXYQVfyG .cluster-label span{color:#333;}#mermaid-svg-oy8TaCzMJXYQVfyG .cluster-label span p{background-color:transparent;}#mermaid-svg-oy8TaCzMJXYQVfyG .label text,#mermaid-svg-oy8TaCzMJXYQVfyG span{fill:#333;color:#333;}#mermaid-svg-oy8TaCzMJXYQVfyG .node rect,#mermaid-svg-oy8TaCzMJXYQVfyG .node circle,#mermaid-svg-oy8TaCzMJXYQVfyG .node ellipse,#mermaid-svg-oy8TaCzMJXYQVfyG .node polygon,#mermaid-svg-oy8TaCzMJXYQVfyG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-oy8TaCzMJXYQVfyG .rough-node .label text,#mermaid-svg-oy8TaCzMJXYQVfyG .node .label text,#mermaid-svg-oy8TaCzMJXYQVfyG .image-shape .label,#mermaid-svg-oy8TaCzMJXYQVfyG .icon-shape .label{text-anchor:middle;}#mermaid-svg-oy8TaCzMJXYQVfyG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-oy8TaCzMJXYQVfyG .rough-node .label,#mermaid-svg-oy8TaCzMJXYQVfyG .node .label,#mermaid-svg-oy8TaCzMJXYQVfyG .image-shape .label,#mermaid-svg-oy8TaCzMJXYQVfyG .icon-shape .label{text-align:center;}#mermaid-svg-oy8TaCzMJXYQVfyG .node.clickable{cursor:pointer;}#mermaid-svg-oy8TaCzMJXYQVfyG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-oy8TaCzMJXYQVfyG .arrowheadPath{fill:#333333;}#mermaid-svg-oy8TaCzMJXYQVfyG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-oy8TaCzMJXYQVfyG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-oy8TaCzMJXYQVfyG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oy8TaCzMJXYQVfyG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-oy8TaCzMJXYQVfyG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oy8TaCzMJXYQVfyG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-oy8TaCzMJXYQVfyG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-oy8TaCzMJXYQVfyG .cluster text{fill:#333;}#mermaid-svg-oy8TaCzMJXYQVfyG .cluster span{color:#333;}#mermaid-svg-oy8TaCzMJXYQVfyG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-oy8TaCzMJXYQVfyG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-oy8TaCzMJXYQVfyG rect.text{fill:none;stroke-width:0;}#mermaid-svg-oy8TaCzMJXYQVfyG .icon-shape,#mermaid-svg-oy8TaCzMJXYQVfyG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oy8TaCzMJXYQVfyG .icon-shape p,#mermaid-svg-oy8TaCzMJXYQVfyG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-oy8TaCzMJXYQVfyG .icon-shape .label rect,#mermaid-svg-oy8TaCzMJXYQVfyG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oy8TaCzMJXYQVfyG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-oy8TaCzMJXYQVfyG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-oy8TaCzMJXYQVfyG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 未初始化
收到 SYN+ACK
超时
应用程序调用 connect
Winsock → TDI_CONNECT IRP
TiDispatchInternal → DispTdiConnect
IoMarkIrpPending
DispPrepareIrpForCancel 设置取消例程
TCPConnect
连接端点状态?
AllocateLocalPort 分配本地端口
调用 IPTransmitPacket 发送 SYN
等待 SYN+ACK
发送 ACK → ESTABLISHED
连接失败
DispDataRequestComplete 完成 IRP
应用程序连接成功
5.3 TCP 数据发送流程
渲染错误: Mermaid 渲染失败: Parse error on line 10: ... --> JTCP 构建 TCP 段 (sk_buff) J --> -----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'PS'
5.4 数据接收流程
#mermaid-svg-H7lVUbspiimfd7ok{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-H7lVUbspiimfd7ok .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-H7lVUbspiimfd7ok .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-H7lVUbspiimfd7ok .error-icon{fill:#552222;}#mermaid-svg-H7lVUbspiimfd7ok .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-H7lVUbspiimfd7ok .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-H7lVUbspiimfd7ok .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-H7lVUbspiimfd7ok .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-H7lVUbspiimfd7ok .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-H7lVUbspiimfd7ok .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-H7lVUbspiimfd7ok .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-H7lVUbspiimfd7ok .marker{fill:#333333;stroke:#333333;}#mermaid-svg-H7lVUbspiimfd7ok .marker.cross{stroke:#333333;}#mermaid-svg-H7lVUbspiimfd7ok svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-H7lVUbspiimfd7ok p{margin:0;}#mermaid-svg-H7lVUbspiimfd7ok .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-H7lVUbspiimfd7ok .cluster-label text{fill:#333;}#mermaid-svg-H7lVUbspiimfd7ok .cluster-label span{color:#333;}#mermaid-svg-H7lVUbspiimfd7ok .cluster-label span p{background-color:transparent;}#mermaid-svg-H7lVUbspiimfd7ok .label text,#mermaid-svg-H7lVUbspiimfd7ok span{fill:#333;color:#333;}#mermaid-svg-H7lVUbspiimfd7ok .node rect,#mermaid-svg-H7lVUbspiimfd7ok .node circle,#mermaid-svg-H7lVUbspiimfd7ok .node ellipse,#mermaid-svg-H7lVUbspiimfd7ok .node polygon,#mermaid-svg-H7lVUbspiimfd7ok .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-H7lVUbspiimfd7ok .rough-node .label text,#mermaid-svg-H7lVUbspiimfd7ok .node .label text,#mermaid-svg-H7lVUbspiimfd7ok .image-shape .label,#mermaid-svg-H7lVUbspiimfd7ok .icon-shape .label{text-anchor:middle;}#mermaid-svg-H7lVUbspiimfd7ok .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-H7lVUbspiimfd7ok .rough-node .label,#mermaid-svg-H7lVUbspiimfd7ok .node .label,#mermaid-svg-H7lVUbspiimfd7ok .image-shape .label,#mermaid-svg-H7lVUbspiimfd7ok .icon-shape .label{text-align:center;}#mermaid-svg-H7lVUbspiimfd7ok .node.clickable{cursor:pointer;}#mermaid-svg-H7lVUbspiimfd7ok .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-H7lVUbspiimfd7ok .arrowheadPath{fill:#333333;}#mermaid-svg-H7lVUbspiimfd7ok .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-H7lVUbspiimfd7ok .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-H7lVUbspiimfd7ok .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H7lVUbspiimfd7ok .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-H7lVUbspiimfd7ok .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H7lVUbspiimfd7ok .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-H7lVUbspiimfd7ok .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-H7lVUbspiimfd7ok .cluster text{fill:#333;}#mermaid-svg-H7lVUbspiimfd7ok .cluster span{color:#333;}#mermaid-svg-H7lVUbspiimfd7ok div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-H7lVUbspiimfd7ok .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-H7lVUbspiimfd7ok rect.text{fill:none;stroke-width:0;}#mermaid-svg-H7lVUbspiimfd7ok .icon-shape,#mermaid-svg-H7lVUbspiimfd7ok .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H7lVUbspiimfd7ok .icon-shape p,#mermaid-svg-H7lVUbspiimfd7ok .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-H7lVUbspiimfd7ok .icon-shape .label rect,#mermaid-svg-H7lVUbspiimfd7ok .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H7lVUbspiimfd7ok .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-H7lVUbspiimfd7ok .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-H7lVUbspiimfd7ok :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 传输层
IP 网络层
LAN/链路层
硬件/NDIS
传统 Receive
Packet Receive
ETYPE_IPv4
ETYPE_ARP
ETYPE_IPv6
是
否
否
是
TCP
UDP
ICMP
是
否
是
否
网卡收到数据帧
NDIS 中断/DPC
接收方式?
ProtocolReceive
ProtocolReceivePacket
NdisTransferData
ProtocolTransferDataComplete
LanReceiveWorker 工作队列
以太网类型?
IPReceive
ARPReceive
IPReceive
验证 IPv4 头
需分片重组?
ReassemblyListHead 管理
等待所有分片
组装完整数据报
目标为本机?
路由器: IPTransmitPacket 转发
IPDispatchProtocol 按协议分发
下一层协议?
TCPReceive
UDPReceive
ICMPReceive
查找连接端点
数据入 TCP 接收队列
HandleSignalledConnection
有等待的 TDI_RECEIVE IRP?
拷贝数据到用户缓冲区
触发 TDI_EVENT_RECEIVE
查找地址文件/端口
有等待的 DG IRP?
复制数据到用户缓冲区
触发 TDI_EVENT_RECEIVE_DATAGRAM
DispDataRequestComplete 完成 IRP
5.5 IP 分片重组流程 (RFC 815)
#mermaid-svg-ojTZUDBAMhyBEreq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ojTZUDBAMhyBEreq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ojTZUDBAMhyBEreq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ojTZUDBAMhyBEreq .error-icon{fill:#552222;}#mermaid-svg-ojTZUDBAMhyBEreq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ojTZUDBAMhyBEreq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ojTZUDBAMhyBEreq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ojTZUDBAMhyBEreq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ojTZUDBAMhyBEreq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ojTZUDBAMhyBEreq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ojTZUDBAMhyBEreq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ojTZUDBAMhyBEreq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ojTZUDBAMhyBEreq .marker.cross{stroke:#333333;}#mermaid-svg-ojTZUDBAMhyBEreq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ojTZUDBAMhyBEreq p{margin:0;}#mermaid-svg-ojTZUDBAMhyBEreq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ojTZUDBAMhyBEreq .cluster-label text{fill:#333;}#mermaid-svg-ojTZUDBAMhyBEreq .cluster-label span{color:#333;}#mermaid-svg-ojTZUDBAMhyBEreq .cluster-label span p{background-color:transparent;}#mermaid-svg-ojTZUDBAMhyBEreq .label text,#mermaid-svg-ojTZUDBAMhyBEreq span{fill:#333;color:#333;}#mermaid-svg-ojTZUDBAMhyBEreq .node rect,#mermaid-svg-ojTZUDBAMhyBEreq .node circle,#mermaid-svg-ojTZUDBAMhyBEreq .node ellipse,#mermaid-svg-ojTZUDBAMhyBEreq .node polygon,#mermaid-svg-ojTZUDBAMhyBEreq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ojTZUDBAMhyBEreq .rough-node .label text,#mermaid-svg-ojTZUDBAMhyBEreq .node .label text,#mermaid-svg-ojTZUDBAMhyBEreq .image-shape .label,#mermaid-svg-ojTZUDBAMhyBEreq .icon-shape .label{text-anchor:middle;}#mermaid-svg-ojTZUDBAMhyBEreq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ojTZUDBAMhyBEreq .rough-node .label,#mermaid-svg-ojTZUDBAMhyBEreq .node .label,#mermaid-svg-ojTZUDBAMhyBEreq .image-shape .label,#mermaid-svg-ojTZUDBAMhyBEreq .icon-shape .label{text-align:center;}#mermaid-svg-ojTZUDBAMhyBEreq .node.clickable{cursor:pointer;}#mermaid-svg-ojTZUDBAMhyBEreq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ojTZUDBAMhyBEreq .arrowheadPath{fill:#333333;}#mermaid-svg-ojTZUDBAMhyBEreq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ojTZUDBAMhyBEreq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ojTZUDBAMhyBEreq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ojTZUDBAMhyBEreq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ojTZUDBAMhyBEreq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ojTZUDBAMhyBEreq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ojTZUDBAMhyBEreq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ojTZUDBAMhyBEreq .cluster text{fill:#333;}#mermaid-svg-ojTZUDBAMhyBEreq .cluster span{color:#333;}#mermaid-svg-ojTZUDBAMhyBEreq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ojTZUDBAMhyBEreq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ojTZUDBAMhyBEreq rect.text{fill:none;stroke-width:0;}#mermaid-svg-ojTZUDBAMhyBEreq .icon-shape,#mermaid-svg-ojTZUDBAMhyBEreq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ojTZUDBAMhyBEreq .icon-shape p,#mermaid-svg-ojTZUDBAMhyBEreq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ojTZUDBAMhyBEreq .icon-shape .label rect,#mermaid-svg-ojTZUDBAMhyBEreq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ojTZUDBAMhyBEreq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ojTZUDBAMhyBEreq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ojTZUDBAMhyBEreq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 没有
有
是
否
是
否
收到 IP 分片
检查 Identification, Src, Dst
已有重装结构?
创建 IPDATAGRAM_REASSEMBLY
找到对应的 IPDR
创建初始 Hole: first=0, last=Max
将分片加入 FragmentList
分片覆盖空洞?
分裂/缩小 Hole
丢弃重叠分片
Hole 列表为空?
组装完成
继续等待更多分片
按顺序拼接各分片数据
释放 IPDR
IPDispatchProtocol
6. 数据流图
6.1 发送数据流
应用程序 (Socket)
|
| send()
v
Winsock 子系统 (afd.sys)
|
| TDI_SEND (IRP_MJ_INTERNAL_DEVICE_CONTROL)
v
tcpip.sys ──── TiDispatchInternal
| |
| DispTdiSend
| |
| TCPSendData
| |
| ┌──────────┴──────────┐
| | TCP 连接型 | UDP 数据报型
| TCP 分段/窗口管理 UDP 数据报构造
| ┌────┴────┐ ┌─┴─┐
| | sk_buff | | |
| | 队列管理 | | |
| └────┬────┘ └─┬─┘
| └────────┬───────────┘
| |
| IPTransmitPacket
| |
| ┌────────┴────────┐
| | 路由查找 |
| | RouteGetRoute |
| └────────┬────────┘
| |
| ┌────────┴────────┐
| | MTU 分片? |
| | (IPFragment) |
| └────────┬────────┘
| |
| ┌────────┴────────┐
| | 邻居缓存 |
| | NBQueuePacket |
| └────────┬────────┘
| |
| ┌────────┴────────┐
| | ARP 解析? |
| | (如有必要) |
| └────────┬────────┘
| |
| LANTransmit
| |
| 封以太网头 + NdisSend
v
NDIS 库 (ndis.sys)
|
| MiniportSend
v
网卡驱动 → 硬件发送
6.2 接收数据流
网卡硬件
|
| 中断 → ISR → DPC
v
NDIS 库 (ndis.sys)
|
| MiniIndicateReceive / MiniIndicateReceivePacket
v
tcpip.sys ──── LAN 层
| |
| ProtocolReceivePacket/ProtocolReceive
| |
| LanReceiveWorker (工作队列)
| |
| ┌────────┴────────┐
| | 解析以太网类型 |
| └────────┬────────┘
| |
| ┌────────┴────────┐
| | IPReceive / |
| | ARPReceive |
| └────────┬────────┘
| |
| ┌────────┴────────┐
| | IP 头校验 |
| | 分片重组 |
| | IPDispatch |
| └────────┬────────┘
| |
| ┌────────┴────────┐
| | 协议号分发 |
| └────────┬────────┘
| |
| ┌───────┴───────┐
| | |
| TCPReceive UDPReceive
| | |
| ┌──┴──┐ ┌───┴───┐
| |查找 | |查找 |
| |连接 | |端口 |
| |端点 | |文件 |
| └──┬──┘ └───┬───┘
| | |
| ┌──┴──┐ ┌───┴───┐
| |数据 | |触发 |
| |入队 | |TDI_ |
| |通知 | |EVENT |
| |IRP | |或完成 |
| └──┬──┘ │IRP |
| | └───┬───┘
| ┌──┴──┐ |
| |完成 IRP 或 |
| |触发事件 |
| └──┬──┘ |
| └──────┬───────┘
| |
| DispDataRequestComplete
| |
v IoCompleteRequest
|
应用程序 (通过事件或 IRP 完成收到数据)
6.3 TDI 事件模型
用户态应用程序
|
| 1. CreateFile("\Device\Tcp")
| 2. TDI_SET_EVENT_HANDLER (注册事件回调)
| 3. TDI_CONNECT / TDI_LISTEN
v
tcpip.sys
|
├── DispTdiSetEventHandler
| └── 注册到 ADDRESS_FILE
| ├── ConnectHandler
| ├── ReceiveHandler
| ├── DisconnectHandler
| ├── ReceiveDatagramHandler
| └── ErrorHandler
|
├── 数据到达时
| └── 如果己注册对应事件处理器
| └── 调用 TDI 事件回调 → 通知上层
|
└── 无对应事件处理器时
└── 挂起 IRP → DispPrepareIrpForCancel
→ 等待 DispDataRequestComplete 完成
7. 初始化序列
7.1 完整的系统-网络初始化序列
Phase 1: NDIS + TCPIP 内核模块加载
====================================
1. 系统加载 ndis.sys → DriverEntry 初始化全局列表
2. 系统加载 tcpip.sys → DriverEntry 执行:
Phase 2: TCP/IP 内部初始化
===========================
3. tcpip.sys DriverEntry:
a. KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn) --- 周期超时 DPC
b. KeInitializeTimer(&IPTimer) --- 每秒触发
c. IoCreateDevice 创建:
- \Device\Ip (FILE_DEVICE_NETWORK)
- \Device\RawIp (FILE_DEVICE_NETWORK)
- \Device\Udp (FILE_DEVICE_NETWORK)
- \Device\Tcp (FILE_DEVICE_NETWORK)
d. ChewInit --- 初始化工作队列
e. 分配 NDIS 包池 (500+1500) 和缓冲区池 (2000)
f. 初始化全局列表:
- AddressFileListHead
- ConnectionEndpointListHead
- InterfaceListHead
Phase 3: 协议子系统启动
=======================
4. IPStartup:
a. 清空 ProtocolTable[256] 协议表
b. 初始化 ReassemblyListHead (分片重组)
c. 初始化 IPDRList / IPFragmentList / IPHoleList (内存后备列表)
d. 初始化 NetTableListHead (网络表)
5. RawIPStartup / UDPStartup / TCPStartup / ICMPStartup:
a. 初始化各自的资源
b. 注册到 IP 层: IPRegisterProtocol(IPPROTO_xxx, Handler)
c. TCP 额外: 初始化连接端点列表、端口分配管理
6. 注册 IRP 分发:
IRP_MJ_CREATE → TiDispatchOpenClose
IRP_MJ_CLOSE → TiDispatchOpenClose
IRP_MJ_INTERNAL_DEVICE_CONTROL → TiDispatchInternal
IRP_MJ_DEVICE_CONTROL → TiDispatch
Phase 4: 回环适配器 + NDIS 注册
===============================
7. LoopRegisterAdapter --- 创建回环接口 (127.0.0.1/8)
a. IPCreateInterface 创建
b. IPRegisterInterface 注册到 InterfaceListHead
8. LANRegisterProtocol --- 注册到 NDIS:
a. 填充 NDIS_PROTOCOL_CHARACTERISTICS (14+ 个回调函数)
b. NdisRegisterProtocol → NDIS 调用 ProtocolBindAdapter
Phase 5: NDIS 绑定微型端口
===========================
9. NDIS 枚举所有微型端口:
a. 对 e1000/rtl8139 等每个适配器:
- ProtocolBindAdapter → LANRegisterAdapter
- NdisOpenAdapter 打开适配器
- 查询 MAC 地址、MTU、介质类型
- ReadIpConfiguration 从注册表读 IP 地址/掩码/网关
- IPCreateInterface 创建 IP 接口
- IPRegisterInterface 注册到全局列表
- 设置以太网数据包过滤器
- 发送 MEDIA_CONNECT 状态事件
b. TCPUpdateInterfaceIPInformation/LinkStatus 更新 TCP 信息
Phase 6: 系统就绪
=================
10. 启动周期计时器 (IP_TIMEOUT = 1000ms)
11. 网络栈就绪,等待用户态请求
8. 关键函数分析
8.1 驱动入口和分发
| 函数 | 位置 | 功能 |
|---|---|---|
DriverEntry |
main.c(file:///d:/reactos/drivers/network/tcpip/tcpip/main.c#L835-L1030) | 创建设备、初始化子系统、注册 NDIS 协议 |
TiUnload |
main.c(file:///d:/reactos/drivers/network/tcpip/tcpip/main.c#L770-L833) | 驱动卸载,按逆序释放所有资源 |
TiDispatchInternal |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L377-L477) | TDI IRP 分发主入口,24 种 Minor Function 处理 |
TiDispatch |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L491-L561) | Device IOCTL 分发(TDI 扩展查询、IP 设置、ICMP 等) |
TiCreateFileObject |
main.c(file:///d:/reactos/drivers/network/tcpip/tcpip/main.c#L113-L275) | 创建地址文件/连接端点/控制通道文件对象 |
8.2 TDI 调度函数
| 函数 | 位置 | 功能 |
|---|---|---|
DispTdiConnect |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L382-L443) | TCP 连接,调用 TCPConnect |
DispTdiListen |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L550-L659) | TCP 监听,创建 Listener + TCPListen + TCPAccept |
DispTdiSend |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L945-L1015) | TCP 发送,调用 TCPSendData |
DispTdiReceive |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L802-L867) | TCP 接收,调用 TCPReceiveData |
DispTdiSendDatagram |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L1018-L1100) | UDP 数据报发送 |
DispTdiReceiveDatagram |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L870-L942) | UDP 数据报接收 |
DispTdiSetEventHandler |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L1103-L1263) | 注册 TDI 事件回调 |
DispTdiAssociateAddress |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L270-L379) | 将连接端点与地址文件关联 |
IRPFinish |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L26-L39) | IRP 完成包装(增加网络优先级) |
8.3 网络层函数
| 函数 | 位置 | 功能 |
|---|---|---|
IPReceive |
receive.c(file:///d:/reactos/drivers/network/tcpip/ip/network/receive.c) | IP 数据报接收入口,负责分片重组和协议分发 |
IPTransmitPacket |
transmit.c(file:///d:/reactos/drivers/network/tcpip/ip/network/transmit.c) | IP 数据报发送入口,负责路由/分片/邻居队列 |
IPSendFragment |
transmit.c(file:///d:/reactos/drivers/network/tcpip/ip/network/transmit.c#L41-L60) | 发送 IP 分片到邻居缓存队列 |
IPDispatchProtocol |
ip.c(file:///d:/reactos/drivers/network/tcpip/ip/network/ip.c) | 按 IP 协议号分发给传输层处理函数 |
IPRegisterProtocol |
ip.c(file:///d:/reactos/drivers/network/tcpip/ip/network/ip.c) | 注册传输层协议处理函数 |
IPCreateInterface |
interface.c(file:///d:/reactos/drivers/network/tcpip/ip/network/interface.c) | 从 LLIP_BIND_INFO 创建 IP 接口 |
IPRegisterInterface |
interface.c(file:///d:/reactos/drivers/network/tcpip/ip/network/interface.c) | 注册 IP 接口 |
RouteGetRouteToDestination |
route.c(file:///d:/reactos/drivers/network/tcpip/ip/network/route.c) | 路由查找 |
8.4 传输层函数
| 函数 | 位置 | 功能 |
|---|---|---|
TCPSocket |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | 创建 TCP socket(初始化 Linux tcp_opt) |
TCPConnect |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | 发起 TCP 连接 |
TCPListen |
accept.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c) | TCP 监听 |
TCPAccept |
accept.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/accept.c) | TCP 接受连接 |
TCPSendData |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | TCP 数据发送 |
TCPReceiveData |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | TCP 数据接收 |
TCPDisconnect |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | TCP 断开连接 |
HandleSignalledConnection |
tcp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/tcp/tcp.c) | TCP 事件驱动处理 |
UDPSend |
udp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/udp/udp.c) | UDP 数据报发送 |
UDPReceive |
udp.c(file:///d:/reactos/drivers/network/tcpip/ip/transport/udp/udp.c) | UDP 数据报接收 |
8.5 LAN/链路层函数
| 函数 | 位置 | 功能 |
|---|---|---|
LANRegisterProtocol |
lan.c(file:///d:/reactos/drivers/network/tcpip/datalink/lan.c#L1673-L1728) | 注册 NDIS 协议驱动 |
LANRegisterAdapter |
lan.c(file:///d:/reactos/drivers/network/tcpip/datalink/lan.c#L1452-L1578) | 打开 NDIS 适配器并绑定到 IP |
LANTransmit |
lan.c(file:///d:/reactos/drivers/network/tcpip/datalink/lan.c#L963-L1091) | 链路层发送(加以太网头 + NdisSend) |
LanReceiveWorker |
lan.c(file:///d:/reactos/drivers/network/tcpip/datalink/lan.c#L307-L386) | 接收工作线程,按以太网类型分发 |
ProtocolReceive |
lan.c(file:///d:/reactos/drivers/network/tcpip/datalink/lan.c#L462-L554) | 传统 NDIS 接收回调 |
ProtocolReceivePacket |
lan.c(file:///d:/reactos/drivers/network/tcpip/datalink/lan.c#L442-L460) | NDIS 数据包接收回调 |
ProtocolSendComplete |
lan.c(file:///d:/reactos/drivers/network/tcpip/datalink/lan.c#L292-L305) | 发送完成回调(释放 NDIS 数据包) |
ProtocolStatus |
lan.c(file:///d:/reactos/drivers/network/tcpip/datalink/lan.c#L824-L900) | NDIS 状态变化回调(连接/断开/重置) |
ReadIpConfiguration |
lan.c(file:///d:/reactos/drivers/network/tcpip/datalink/lan.c#L568-L731) | 从注册表读取 IP 配置 |
8.6 辅助函数
| 函数 | 位置 | 功能 |
|---|---|---|
AllocatePacketWithBuffer |
buffer.c(file:///d:/reactos/drivers/network/tcpip/tcpip/buffer.c) | 分配 NDIS 包 + 关联 MDL 缓冲区 |
FreeNdisPacket |
buffer.c(file:///d:/reactos/drivers/network/tcpip/tcpip/buffer.c) | 释放 NDIS 包 |
ChewCreate |
workqueue.c(file:///d:/reactos/drivers/network/tcpip/chew/workqueue.c) | 创建工作项 |
DispDataRequestComplete |
dispatch.c(file:///d:/reactos/drivers/network/tcpip/tcpip/dispatch.c#L87-L116) | 数据请求完成通用回调 |
9. 构建配置
9.1 CMakeLists.txt
cmake
add_definitions(
-DNDIS40
-D_NTDRIVER_)
add_library(tcpip MODULE
chew/workqueue.c
datalink/lan.c
tcpip/ainfo.c
tcpip/buffer.c
tcpip/cinfo.c
tcpip/dispatch.c
tcpip/fileobjs.c
tcpip/icmp.c
tcpip/iinfo.c
tcpip/info.c
tcpip/lock.c
tcpip/main.c
tcpip/ninfo.c
tcpip/proto.c
tcpip/tinfo.c
tcpip/wait.c
...)
target_link_libraries(tcpip ip ${PSEH_LIB})
set_module_type(tcpip kernelmodedriver)
add_importlibs(tcpip ndis ntoskrnl hal)
9.2 输出
编译结果为 reactos/system32/drivers/tcpip.sys,链接 ip 库(ip/CMakeLists.txt 编译的子库)、ndis、ntoskrnl、hal。
9.3 依赖关系
tcpip.sys
├── ip 库 (ReactOS IP 协议栈)
│ ├── network/ (IP/ARP/ICMP/路由/邻居)
│ ├── transport/ (TCP/UDP/RawIP)
│ └── lwip_glue/ (lwIP 粘合)
├── ndis (NDIS 接口)
├── ntoskrnl (内核 API)
└── hal (硬件抽象层)
附录 A:NDIS 协议驱动特性
c
// tcpip.sys 注册到 NDIS 的协议特性 (lan.c)
ProtChars.MajorNdisVersion = NDIS_VERSION_MAJOR; // 4
ProtChars.MinorNdisVersion = NDIS_VERSION_MINOR; // 0
ProtChars.OpenAdapterCompleteHandler = ProtocolOpenAdapterComplete;
ProtChars.CloseAdapterCompleteHandler = ProtocolCloseAdapterComplete;
ProtChars.ResetCompleteHandler = ProtocolResetComplete;
ProtChars.RequestCompleteHandler = ProtocolRequestComplete;
ProtChars.SendCompleteHandler = ProtocolSendComplete;
ProtChars.TransferDataCompleteHandler = ProtocolTransferDataComplete;
ProtChars.ReceivePacketHandler = ProtocolReceivePacket; // NDIS 5.0
ProtChars.ReceiveHandler = ProtocolReceive;
ProtChars.ReceiveCompleteHandler = ProtocolReceiveComplete;
ProtChars.StatusHandler = ProtocolStatus;
ProtChars.StatusCompleteHandler = ProtocolStatusComplete;
ProtChars.BindAdapterHandler = ProtocolBindAdapter;
ProtChars.PnPEventHandler = ProtocolPnPEvent;
ProtChars.UnbindAdapterHandler = ProtocolUnbindAdapter;
附录 B:关键头文件索引
| 头文件 | 路径 | 说明 |
|---|---|---|
tcpip.h |
include/tcpip.h(file:///d:/reactos/drivers/network/tcpip/include/tcpip.h) | 主头文件,全局变量、字节序宏 |
titypes.h |
include/titypes.h(file:///d:/reactos/drivers/network/tcpip/include/titypes.h) | 核心类型:ADDRESS_FILE、引用计数、锁 |
ticonsts.h |
include/ticonsts.h(file:///d:/reactos/drivers/network/tcpip/include/ticonsts.h) | 常量定义 |
ip.h |
include/ip.h(file:///d:/reactos/drivers/network/tcpip/include/ip.h) | IP 层:IP_PACKET、IP_INTERFACE、LLIP_BIND_INFO |
tcp.h |
include/tcp.h(file:///d:/reactos/drivers/network/tcpip/include/tcp.h) | TCP 层:TCPv4_HEADER、TCP_COMPLETION_ROUTINE |
tcpcore.h |
include/tcpcore.h(file:///d:/reactos/drivers/network/tcpip/include/tcpcore.h) | Linux 内核移植:sk_buff、tcp_opt、sock 等 |
lan.h |
include/lan.h(file:///d:/reactos/drivers/network/tcpip/include/lan.h) | 数据链路层:LAN_ADAPTER |
arp.h |
include/arp.h(file:///d:/reactos/drivers/network/tcpip/include/arp.h) | ARP 协议 |
route.h |
include/route.h(file:///d:/reactos/drivers/network/tcpip/include/route.h) | 路由表 |
neighbor.h |
include/neighbor.h(file:///d:/reactos/drivers/network/tcpip/include/neighbor.h) | 邻居缓存 (NCE) |
receive.h |
include/receive.h(file:///d:/reactos/drivers/network/tcpip/include/receive.h) | IP 接收 |
transmit.h |
include/transmit.h(file:///d:/reactos/drivers/network/tcpip/include/transmit.h) | IP 发送 |
interface.h |
include/interface.h(file:///d:/reactos/drivers/network/tcpip/include/interface.h) | 接口管理 |
udp.h |
include/udp.h(file:///d:/reactos/drivers/network/tcpip/include/udp.h) | UDP |
icmp.h |
include/icmp.h(file:///d:/reactos/drivers/network/tcpip/include/icmp.h) | ICMP |
rawip.h |
include/rawip.h(file:///d:/reactos/drivers/network/tcpip/include/rawip.h) | Raw IP |
dispatch.h |
include/dispatch.h(file:///d:/reactos/drivers/network/tcpip/include/dispatch.h) | TDI 分发函数声明 |
fileobjs.h |
include/fileobjs.h(file:///d:/reactos/drivers/network/tcpip/include/fileobjs.h) | 文件对象管理 |
info.h |
include/info.h(file:///d:/reactos/drivers/network/tcpip/include/info.h) | TDI 信息查询 |
lock.h |
include/lock.h(file:///d:/reactos/drivers/network/tcpip/include/lock.h) | 锁操作 |
wait.h |
include/wait.h(file:///d:/reactos/drivers/network/tcpip/include/wait.h) | 等待操作 |
附录 C:TCP 状态机
+---------+
| CLOSED |
+----+----+
|
主动打开 / 被动打开
|
+----v----+
| LISTEN |
+----+----+
| 收到 SYN
+----v----+
| SYN_RCV |
+----+----+
| 发送 SYN+ACK
|
主动打开 | 同时打开
+----v----+ +----v----+
| SYN_SENT+--------> SYN_RCV |
+----+----+ +----+----+
| |
| 收到 SYN+ACK | 收到 ACK
+--------+--------+
|
+------v------+
| ESTABLISHED |
+------+------+
|
+------+------+
| 主动关闭/被动关闭 |
+------+------+
|
+------v------+
| FIN_WAIT_1 | +---------+
+------+------+ |CLOSE_WAIT|
| +----+----+
+------v------+ |
| FIN_WAIT_2 | | 关闭
+------+------+ +----v----+
| |LAST_ACK |
+------v------+ +----+----+
| TIME_WAIT | |
+------+------+ |
| |
+------v------+ |
| CLOSED |<--------------+
+-------------+
附录 D:参考文档
- NDIS 驱动分析(file:///d:/reactos/doc/NDIS_驱动分析.md) --- NDIS 库详细分析
- ddk/ndis.h(file:///d:/reactos/sdk/include/ddk/ndis.h) --- NDIS DDK 头文件
- tdikrnl.h(file:///d:/reactos/sdk/include/ddk/tdikrnl.h) --- TDI 内核接口头文件
- tcpcore.h(file:///d:/reactos/drivers/network/tcpip/include/tcpcore.h) --- Linux TCP 内核移植
- lwIP 源码(file:///d:/reactos/drivers/network/tcpip/lwip/) --- lwIP 协议栈
- RFC 793 --- Transmission Control Protocol
- RFC 791 --- Internet Protocol
- RFC 815 --- IP Datagram Reassembly Algorithms
- RFC 826 --- Ethernet Address Resolution Protocol