diff --git a/tcpip/ports/port.go b/tcpip/ports/port.go new file mode 100644 index 0000000..ac40939 --- /dev/null +++ b/tcpip/ports/port.go @@ -0,0 +1,28 @@ +package ports + +import ( + "sync" + + "github.com/impact-eintr/netstack/tcpip" +) + +const ( + // 临时端口的最小值 + anyIPAddress tcpip.Address = "" +) + +// 管理端口的唯一标识: 网络层协议-传输层协议-端口号 +type portDescriptor struct { + network tcpip.NetworkProtocolNumber + transport tcpip.TransportProtocolNumber + port uint16 +} + +// 管理端口的对象 由它来保留和释放端口 +type PortManager struct { + mu sync.RWMutex + // 用一个map来保存被占用的端口 + allocatedPorts map[portDescriptor]bindAddresses +} + +type bindAddresses map[tcpip.Address]struct{} diff --git a/tcpip/stack/linkaddresscache.go b/tcpip/stack/linkaddresscache.go new file mode 100644 index 0000000..8200ef8 --- /dev/null +++ b/tcpip/stack/linkaddresscache.go @@ -0,0 +1,45 @@ +package stack + +import ( + "sync" + "time" + + "github.com/impact-eintr/netstack/tcpip" +) + +const linkAddrCacheSize = 512 // 最大缓存条目 + +// 是一个固定大小的缓存,将 IP 地址映射到链接地址 +// 条目存储在环形缓冲区中,最旧的条目首先被替换。 +// 这个结构体对于并发使用是安全的 +type linkAddrCache struct { + // 缓存条目的有效期 + ageLimit time.Duration + // 等待链接请求解析地址的时间 + resolutionTimeout time.Duration + // 地址在失败前尝试解析的次数 + resolutionAttempts int + + mu sync.Mutex + cache map[tcpip.FullAddress]*linkAddrEntry + next int // 下一个可用条目的数组索引 + entries [linkAddrCacheSize]linkAddrEntry +} + +// linkAddrCache 中的一个条目 +type linkAddrEntry struct { + addr tcpip.FullAddress + linkAddr tcpip.LinkAddress + expiration time.Time + s entryState +} + +// entryState 控制缓存中单个条目的状态 +type entryState int + +const ( + incomplete entryState = iota + ready + failed + expired // 失效的 +) diff --git a/tcpip/stack/nic.go b/tcpip/stack/nic.go index e949c3d..c1e0d48 100644 --- a/tcpip/stack/nic.go +++ b/tcpip/stack/nic.go @@ -1,5 +1,11 @@ package stack +import ( + "sync" + + "github.com/impact-eintr/netstack/tcpip" +) + type referencedNetworkEndpoint struct { //ilist.Entry //refs int32 @@ -9,3 +15,25 @@ type referencedNetworkEndpoint struct { //linkCache LinkAddressCache //holdsInserRef bool } + +// 代表一个网卡对象 +type NIC struct { + stack *Stack + // 每个网卡唯一的标识号 + id tcpip.NICID + // 网卡名 可有可无 + name string + // 链路层端 + linkEP LinkEndpoint + // 传输层的解复用 + demux *transportDemuxer + + mu sync.RWMutex + spoofing bool + promiscuous bool + primary map[tcpip.NetworkProtocolNumber]*ilist.List + // 网络层端的记录 + endpoints map[tcpip.NetworkEndpointID]*referencedNetworkEndpoint + // 子网的记录 + subnets []tcpip.Subnet +} diff --git a/tcpip/stack/registration.go b/tcpip/stack/registration.go index 396dea5..bc46e02 100644 --- a/tcpip/stack/registration.go +++ b/tcpip/stack/registration.go @@ -46,13 +46,6 @@ const ( CapabilityLoopback ) -// 包含网络协议栈用于在 数据链路层 处理数据包后将数据包传送到适当网络端点的方法。 -type NetworkDispatcher interface { - // deliver 递送 - DeliverNetworkPacket(linkEP LinkEndpoint, dstLinkAddr, srcLinkAddr tcpip.LinkAddress, - protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) -} - var ( // 传输层协议的注册存储结构 //transportProtocols = make(map[string]TransportProtocolFactory) @@ -77,3 +70,29 @@ func RegisterLinkEndpoint(linkEP LinkEndpoint) tcpip.LinkEndpointID { return v } + +type TransportProtocol interface { +} + +type TransportEndpointID struct { + LocalPort uint16 + LocalAddress tcpip.Address + RemotePort uint16 + RemoteAddress tcpip.Address +} + +type NetworkProtocol interface { + //Number() tcpip.NetworkProtocolNumber + //MinimumPacketSize() int + //ParseAddresses(v buffer.View) (src, dst tcpip.Address) +} + +// 包含网络协议栈用于在 数据链路层 处理数据包后将数据包传送到适当网络端点的方法。 +type NetworkDispatcher interface { + // deliver 递送 + DeliverNetworkPacket(linkEP LinkEndpoint, dstLinkAddr, srcLinkAddr tcpip.LinkAddress, + protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) +} + +type LinkAddressResolver interface { +} diff --git a/tcpip/stack/stack.go b/tcpip/stack/stack.go new file mode 100644 index 0000000..9b15899 --- /dev/null +++ b/tcpip/stack/stack.go @@ -0,0 +1,48 @@ +package stack + +import ( + "sync" + + "github.com/impact-eintr/netstack/tcpip" + "github.com/impact-eintr/netstack/tcpip/buffer" + "github.com/impact-eintr/netstack/tcpip/ports" +) + +type transportProtocolState struct { + proto TransportProtocol + defaultHandler func(*Route, TransportEndpointID, buffer.VectorisedView) bool +} + +type Stack struct { + transportProtocols map[tcpip.TransportProtocolNumber]*transportProtocolState + networkProtocols map[tcpip.NetworkProtocolNumber]NetworkProtocol + linkAddrResolvers map[tcpip.NetworkProtocolNumber]LinkAddressResolver + + demux *transportDemuxer + + stats tcpip.Stats + + linkAddrCache *linkAddrCache + + mu sync.RWMutex + nics map[tcpip.NICID]*NIC + forwarding bool + + routeTable []tcpip.Route + + *ports.PortManager + tcpProbeFunc TCPProbeFunc + clock tcpip.Clock +} + +type Options struct { + Clock tcpip.Clock + Stats tcpip.Stats +} + +// TCPProbeFunc 是要传递给 stack.AddTCPProbe 的 TCP 探测函数的预期函数类型 +type TCPProbeFunc func(s TCPEndpointState) + +// TCPEndpointState 是 TCP 端点内部状态的副本 +type TCPEndpointState struct { +} diff --git a/tcpip/stack/transport_demuxer.go b/tcpip/stack/transport_demuxer.go new file mode 100644 index 0000000..311d3b9 --- /dev/null +++ b/tcpip/stack/transport_demuxer.go @@ -0,0 +1,25 @@ +package stack + +import ( + "sync" + + "github.com/impact-eintr/netstack/tcpip" +) + +// 解复用针对传输端点的数据包 在他们被网络层解析之后 +// 它执行两级解复用 首先基于网络协议和传输协议 然后基于端点ID +type transportDemuxer struct { + protocol map[protocolIDs]*transportEndpoints +} + +// 管理给定协议的所有端点 +type transportEndpoints struct { + mu sync.RWMutex + endpoints map[TransportEndpointID]*transportEndpoints +} + +// 网络层协议号和传输层协议号的组合 当作分流器的key值 +type protocolIDs struct { + network tcpip.NetworkProtocolNumber + transport tcpip.TransportProtocolNumber +} diff --git a/tcpip/tcpip.go b/tcpip/tcpip.go index cb90618..1862074 100644 --- a/tcpip/tcpip.go +++ b/tcpip/tcpip.go @@ -92,11 +92,94 @@ func ParseMACAddress(s string) (LinkAddress, error) { } type NetworkProtocolNumber uint32 +type TransportProtocolNumber uint32 + type Address string +func (a Address) String() string { + return "" +} + type ProtocolAddr struct { Protocol NetworkProtocolNumber Address Address } type LinkEndpointID uint64 + +type Stats struct { + UnknowProtocolRcvdPackets *StatCounter + MalformedRcvdPackets *StatCounter + DroppedPackets *StatCounter + IP IPStats + TCP TCPStats + UDP UDPStats +} + +type StatCounter struct { + count uint64 +} + +type IPStats struct { + PacketsReceived *StatCounter + InvalidAddressReceived *StatCounter + PacketsDelivered *StatCounter + PacketsSent *StatCounter + OutgoingPacketErrors *StatCounter +} + +type TCPStats struct { + ActiveConnectionOpenings *StatCounter + PassiveConnectionOpenings *StatCounter + FailedConnectionAttempts *StatCounter + ValidSegmentReveived *StatCounter + InvalidSegmentReveived *StatCounter + + SegmentsSents *StatCounter + ResetsSent *StatCounter + ResetsReceived *StatCounter +} + +type UDPStats struct { + PacketReceived *StatCounter + UnknownPortErrors *StatCounter + ReceiveBufferErrors *StatCounter + MalformedPacketsReceived *StatCounter + PacketsSent *StatCounter +} + +// FullAddress 表示完整的传输节点地址,这是 Connect() 和 Bind() 方法所要求的 +type FullAddress struct { + NIC NICID // NIC 是这个地址所指的 NIC 的 ID + Addr Address // 网络地址 + Port uint16 // 传输层端口 +} + +type NICID int32 + +// Route 是路由表中的一行。它指定应通过哪些 NIC(和网关)组路由数据包。 +// 如果屏蔽的目标地址与行中的目标地址匹配,则该行被认为是可行的 +type Route struct { + Destination Address + // 掩码指定目标地址和目标地址的哪些位必须匹配才能使该行可行 + Mask AddressMask + Gateway Address + NIC NICID +} + +type AddressMask string + +func (a AddressMask) String() string { + return Address(a).String() +} + +type Subnet struct { + address Address + mask AddressMask +} + +// 提供现在时刻的接口 +type Clock interface { + NowNanoseconds() int64 + NowMonoseconds() int64 +}