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)
| 1685 | // WireGuard outbound. This is a regression test for a bug where self-dial |
| 1686 | // packets were sent to WireGuard and silently dropped. |
| 1687 | func 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) |
nothing calls this directly
no test coverage detected
searching dependent graphs…