mirror of
https://github.com/impact-eintr/netstack.git
synced 2025-10-06 21:32:59 +08:00
172 lines
5.1 KiB
Go
172 lines
5.1 KiB
Go
package fragmentation_test
|
|
|
|
import (
|
|
"log"
|
|
"math"
|
|
"netstack/tcpip"
|
|
"netstack/tcpip/buffer"
|
|
"netstack/tcpip/header"
|
|
"netstack/tcpip/link/channel"
|
|
"netstack/tcpip/network/arp"
|
|
"netstack/tcpip/network/ipv4"
|
|
"netstack/tcpip/stack"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
stackLinkAddr = tcpip.LinkAddress("\x0a\x0a\x0b\x0b\x0c\x0c") // 0a:0a:0b:0b:0c:0c
|
|
stackAddr1 = tcpip.Address("\x0a\x00\x00\x01") // 10.0.0.1
|
|
stackAddr2 = tcpip.Address("\x0a\x00\x00\x02") // 10.0.0.2
|
|
stackAddrBad = tcpip.Address("\x0a\x00\x00\x03") // 10.0.0.3
|
|
)
|
|
|
|
type testContext struct {
|
|
t *testing.T
|
|
linkEP *channel.Endpoint
|
|
s *stack.Stack
|
|
id uint16
|
|
}
|
|
|
|
func newTestContext(t *testing.T) *testContext {
|
|
s := stack.New([]string{ipv4.ProtocolName, arp.ProtocolName}, nil, stack.Options{})
|
|
|
|
const defaultMTU = 65536
|
|
id, linkEP := channel.New(256, defaultMTU, stackLinkAddr)
|
|
if err := s.CreateNIC(1, id); err != nil {
|
|
t.Fatalf("CreateNIC failed: %v", err)
|
|
}
|
|
|
|
if err := s.AddAddress(1, ipv4.ProtocolNumber, stackAddr1); err != nil {
|
|
t.Fatalf("AddAddress for ipv4 failed: %v", err)
|
|
}
|
|
if err := s.AddAddress(1, ipv4.ProtocolNumber, stackAddr2); err != nil {
|
|
t.Fatalf("AddAddress for ipv4 failed: %v", err)
|
|
}
|
|
if err := s.AddAddress(1, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
|
|
t.Fatalf("AddAddress for arp failed: %v", err)
|
|
}
|
|
|
|
s.SetRouteTable([]tcpip.Route{{
|
|
Destination: "\x00\x00\x00\x00",
|
|
Mask: "\x00\x00\x00\x00",
|
|
Gateway: "",
|
|
NIC: 1,
|
|
}})
|
|
|
|
return &testContext{
|
|
t: t,
|
|
s: s,
|
|
linkEP: linkEP,
|
|
id: uint16(time.Now().Unix() % math.MaxUint16),
|
|
}
|
|
}
|
|
|
|
func (c *testContext) cleanup() {
|
|
close(c.linkEP.C)
|
|
}
|
|
|
|
func TestFragmentationBase(t *testing.T) {
|
|
c := newTestContext(t)
|
|
defer c.cleanup()
|
|
|
|
const senderMAC = "\x01\x02\x03\x04\x05\x06"
|
|
const senderIPv4 = "\x0a\x00\x00\x02"
|
|
|
|
v := make(buffer.View, header.ARPSize)
|
|
h := header.ARP(v)
|
|
h.SetIPv4OverEthernet()
|
|
h.SetOp(header.ARPRequest) // 一个ARP请求
|
|
copy(h.HardwareAddressSender(), senderMAC) // Local MAC
|
|
copy(h.ProtocolAddressSender(), senderIPv4) // Local IP
|
|
|
|
inject := func(addr tcpip.Address) {
|
|
copy(h.ProtocolAddressTarget(), addr)
|
|
c.linkEP.Inject(arp.ProtocolNumber, v.ToVectorisedView()) // 往链路层注入一个arp报文 链路层将会自动分发它
|
|
}
|
|
|
|
inject(stackAddr1) // target IP 10.0.0.1
|
|
select {
|
|
case pkt := <-c.linkEP.C:
|
|
if pkt.Proto != arp.ProtocolNumber {
|
|
t.Fatalf("stackAddr1: expected ARP response, got network protocol number %v", pkt.Proto)
|
|
}
|
|
rep := header.ARP(pkt.Header)
|
|
if !rep.IsValid() {
|
|
t.Fatalf("stackAddr1: invalid ARP response len(pkt.Header)=%d", len(pkt.Header))
|
|
}
|
|
if tcpip.Address(rep.ProtocolAddressSender()) != stackAddr1 {
|
|
t.Errorf("stackAddr1: expected sender to be set")
|
|
}
|
|
if got := tcpip.LinkAddress(rep.HardwareAddressSender()); got != stackLinkAddr {
|
|
t.Errorf("stackAddr1: expected sender to be stackLinkAddr, got %q", got)
|
|
}
|
|
case <-time.After(100 * time.Millisecond):
|
|
t.Fatalf("Case #1 Time Out\n")
|
|
}
|
|
|
|
// 一个纯粹的IP报文 Part1
|
|
pLen := ((1500 - header.EthernetMinimumSize - header.IPv4MinimumSize) >> 3) << 3
|
|
v = make(buffer.View, header.IPv4MinimumSize+pLen)
|
|
hdr := buffer.NewPrependable(header.IPv4MinimumSize)
|
|
ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize))
|
|
buf := make(buffer.View, pLen)
|
|
for i := range buf {
|
|
buf[i] = 1
|
|
}
|
|
payload := buffer.NewVectorisedView(pLen, buf.ToVectorisedView().Views())
|
|
length := uint16(hdr.UsedLength() + payload.Size())
|
|
// ip首部编码
|
|
ip.Encode(&header.IPv4Fields{
|
|
IHL: header.IPv4MinimumSize,
|
|
TotalLength: length,
|
|
ID: c.id,
|
|
Flags: 0x1,
|
|
FragmentOffset: 0,
|
|
TTL: 255,
|
|
Protocol: uint8(0x6), // tcp 伪装报文
|
|
SrcAddr: senderIPv4,
|
|
DstAddr: stackAddr1,
|
|
})
|
|
//ip.SetFlagsFragmentOffset()
|
|
// 计算校验和和设置校验和
|
|
ip.SetChecksum(^ip.CalculateChecksum())
|
|
copy(v, ip)
|
|
copy(v[header.IPv4MinimumSize:], payload.First())
|
|
|
|
inject = func(addr tcpip.Address) {
|
|
copy(h.ProtocolAddressTarget(), addr)
|
|
c.linkEP.Inject(ipv4.ProtocolNumber, v.ToVectorisedView()) // 往链路层注入一个arp报文 链路层将会自动分发它
|
|
}
|
|
|
|
inject(stackAddr1)
|
|
|
|
// 一个纯粹的IP报文 Part2
|
|
pLen = 256
|
|
v = make(buffer.View, header.IPv4MinimumSize+pLen)
|
|
payload = buffer.NewVectorisedView(pLen, buf.ToVectorisedView().Views())
|
|
length = uint16(hdr.UsedLength() + payload.Size())
|
|
// ip首部编码
|
|
ip.Encode(&header.IPv4Fields{
|
|
IHL: header.IPv4MinimumSize,
|
|
TotalLength: length,
|
|
ID: c.id,
|
|
FragmentOffset: 1464,
|
|
TTL: 255,
|
|
Protocol: uint8(0x6), // tcp 伪装报文
|
|
SrcAddr: senderIPv4,
|
|
DstAddr: stackAddr1,
|
|
})
|
|
//ip.SetFlagsFragmentOffset()
|
|
// 计算校验和和设置校验和
|
|
ip.SetChecksum(^ip.CalculateChecksum())
|
|
copy(v, ip)
|
|
copy(v[header.IPv4MinimumSize:], payload.First())
|
|
|
|
inject(stackAddr1)
|
|
|
|
msg := <-c.linkEP.C
|
|
log.Println(msg.Header)
|
|
|
|
}
|