MCPcopy Index your code
hub / github.com/tailscale/tailscale / TestInjectLoopback

Function TestInjectLoopback

wgengine/netstack/netstack_test.go:1687–1749  ·  view source on GitHub ↗

TestInjectLoopback verifies that the inject goroutine delivers self-addressed packets back into gVisor (via DeliverLoopback) instead of sending them to WireGuard outbound. This is a regression test for a bug where self-dial packets were sent to WireGuard and silently dropped.

(t *testing.T)

Source from the content-addressed store, hash-verified

1685// WireGuard outbound. This is a regression test for a bug where self-dial
1686// packets were sent to WireGuard and silently dropped.
1687func TestInjectLoopback(t *testing.T) {
1688 selfIP4 := netip.MustParseAddr("100.64.1.2")
1689
1690 ns := makeNetstack(t, func(impl *Impl) {
1691 impl.ProcessLocalIPs = true
1692 impl.atomicIsLocalIPFunc.Store(func(addr netip.Addr) bool {
1693 return addr == selfIP4
1694 })
1695 })
1696
1697 // Register gVisor's NIC address so the stack accepts and routes
1698 // packets for this IP.
1699 protocolAddr := tcpip.ProtocolAddress{
1700 Protocol: header.IPv4ProtocolNumber,
1701 AddressWithPrefix: tcpip.AddrFrom4(selfIP4.As4()).WithPrefix(),
1702 }
1703 if err := ns.ipstack.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil {
1704 t.Fatalf("AddProtocolAddress: %v", err)
1705 }
1706
1707 // Bind a UDP socket on the gVisor stack to receive the loopback packet.
1708 pc, err := gonet.DialUDP(ns.ipstack, &tcpip.FullAddress{
1709 NIC: nicID,
1710 Addr: tcpip.AddrFrom4(selfIP4.As4()),
1711 Port: 8081,
1712 }, nil, header.IPv4ProtocolNumber)
1713 if err != nil {
1714 t.Fatalf("DialUDP: %v", err)
1715 }
1716 defer pc.Close()
1717
1718 // Build a valid self-addressed UDP packet from raw bytes and wrap it
1719 // in a gVisor PacketBuffer with headers already pushed, as gVisor's
1720 // outbound path produces.
1721 payload := []byte("loopback test")
1722 raw := udp4raw(t, selfIP4, selfIP4, 12345, 8081, payload)
1723
1724 pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
1725 ReserveHeaderBytes: header.IPv4MinimumSize + header.UDPMinimumSize,
1726 Payload: buffer.MakeWithData(payload),
1727 })
1728 copy(pkt.TransportHeader().Push(header.UDPMinimumSize),
1729 raw[header.IPv4MinimumSize:header.IPv4MinimumSize+header.UDPMinimumSize])
1730 pkt.TransportProtocolNumber = header.UDPProtocolNumber
1731 copy(pkt.NetworkHeader().Push(header.IPv4MinimumSize), raw[:header.IPv4MinimumSize])
1732 pkt.NetworkProtocolNumber = header.IPv4ProtocolNumber
1733
1734 if err := ns.linkEP.q.Write(pkt); err != nil {
1735 t.Fatalf("queue.Write: %v", err)
1736 }
1737
1738 // The inject goroutine should detect the self-addressed packet via
1739 // isSelfDst and deliver it back into gVisor via DeliverLoopback.
1740 pc.SetReadDeadline(time.Now().Add(5 * time.Second))
1741 buf := make([]byte, 256)
1742 n, _, err := pc.ReadFrom(buf)
1743 if err != nil {
1744 t.Fatalf("ReadFrom: %v (self-addressed packet was not looped back)", err)

Callers

nothing calls this directly

Calls 14

makeNetstackFunction · 0.85
udp4rawFunction · 0.85
TransportHeaderMethod · 0.80
NetworkHeaderMethod · 0.80
StoreMethod · 0.65
FatalfMethod · 0.65
CloseMethod · 0.65
PushMethod · 0.65
WriteMethod · 0.65
SetReadDeadlineMethod · 0.65
AddMethod · 0.65
NowMethod · 0.65

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…