| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- package amneziawgnet
- import (
- "bytes"
- "encoding/binary"
- "net/netip"
- "testing"
- "time"
- "gvisor.dev/gvisor/pkg/tcpip"
- "gvisor.dev/gvisor/pkg/tcpip/checksum"
- "gvisor.dev/gvisor/pkg/tcpip/header"
- )
- // TestWriteUDPReplyMTU exercises the actual channel-backed TUN output, not a packet builder.
- func TestWriteUDPReplyMTU(t *testing.T) {
- for _, tc := range []struct {
- name string
- payload int
- fragments bool
- }{
- {"small", 32, false}, {"boundary", 1252, false}, {"oversize", 1452, true},
- } {
- t.Run(tc.name, func(t *testing.T) {
- tun, gstack, err := createNetTUNWithStack([]netip.Addr{netip.MustParseAddr("10.77.0.1")}, 1280)
- if err != nil {
- t.Fatal(err)
- }
- defer tun.Close()
- enablePromiscuousRouting(gstack)
- from := netip.MustParseAddrPort("203.0.113.9:5353")
- to := netip.MustParseAddrPort("10.77.0.2:49152")
- payload := make([]byte, tc.payload)
- for i := range payload {
- payload[i] = byte(i*37 + 11)
- }
- if err := WriteUDPReply(gstack, from, to, payload); err != nil {
- t.Fatal(err)
- }
- st := tun.(*stackTun)
- var data []byte
- var received int
- var id uint16
- for {
- select {
- case v := <-st.incomingPacket:
- p := v.AsSlice()
- packet := append([]byte(nil), p...)
- v.Release()
- if len(packet) > 1280 {
- t.Fatalf("TUN packet length %d exceeds MTU 1280", len(packet))
- }
- ip := header.IPv4(packet)
- if ip.SourceAddress().String() != from.Addr().String() || ip.DestinationAddress().String() != to.Addr().String() {
- t.Fatalf("IP addresses %s -> %s", ip.SourceAddress(), ip.DestinationAddress())
- }
- if ip.TotalLength() != uint16(len(packet)) || checksum.Checksum(packet[:ip.HeaderLength()], 0) != 0xffff {
- t.Fatalf("bad IPv4 header, len %d", len(packet))
- }
- if received == 0 {
- id = ip.ID()
- } else if id != ip.ID() {
- t.Fatalf("fragment IDs differ: %d != %d", id, ip.ID())
- }
- offset := int(ip.FragmentOffset())
- part := packet[ip.HeaderLength():]
- if offset != received {
- t.Fatalf("fragment offset %d, expected %d", offset, received)
- }
- data = append(data, part...)
- received += len(part)
- if ip.Flags()&header.IPv4FlagMoreFragments == 0 {
- if tc.fragments && offset == 0 {
- t.Fatal("oversize reply was not fragmented")
- }
- goto reassembled
- }
- case <-time.After(time.Second):
- t.Fatal("timed out waiting for TUN packets")
- }
- }
- reassembled:
- if len(data) != header.UDPMinimumSize+len(payload) {
- t.Fatalf("UDP bytes %d, want %d", len(data), 8+len(payload))
- }
- if binary.BigEndian.Uint16(data[:2]) != from.Port() || binary.BigEndian.Uint16(data[2:4]) != to.Port() || binary.BigEndian.Uint16(data[4:6]) != uint16(len(data)) {
- t.Fatalf("UDP ports/length incorrect: %x", data[:8])
- }
- if !bytes.Equal(data[8:], payload) {
- t.Fatal("UDP payload changed")
- }
- if checksum.Checksum(data, header.PseudoHeaderChecksum(header.UDPProtocolNumber, tcpip.AddrFromSlice(from.Addr().AsSlice()), tcpip.AddrFromSlice(to.Addr().AsSlice()), uint16(len(data)))) != 0xffff {
- t.Fatal("UDP checksum invalid")
- }
- })
- }
- }
|