mirror of
https://github.com/soypat/lneto.git
synced 2026-08-13 11:23:42 +00:00
7d5830d7ab
* begin adding udp.MuxHandler * add udp MuxHandlerSIMO/MIMO * add tcp rx shutdown * icmpv6 client * icmpv6 Client shared NDP/Echo preparation * icmpv6 client ndp/echo split * icmpv6 client ndp/echo split done * icmpv6 adjustments * add dhcpv6 stubs * dhcpv4 preliminary revision * add dns.NextLabel * dns label name tweaks * dns begin work on TCP client * add dnstcp package * apply gofmt changes * add udp mux tests * clean up, remove StackBig for now * remove dnstcp so as to merged confident parts and we continue dnstcp work elsewhere
123 lines
3.3 KiB
Go
123 lines
3.3 KiB
Go
package icmpv6
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
)
|
|
|
|
func TestClientNDP(t *testing.T) {
|
|
addr1 := [16]byte{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
|
addr2 := [16]byte{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}
|
|
mac1 := [6]byte{0xde, 0xad, 0xbe, 0xef, 0x00, 0x01}
|
|
mac2 := [6]byte{0xc0, 0xff, 0xee, 0xc0, 0xff, 0x02}
|
|
|
|
var h1, h2 Client
|
|
if err := h1.Configure(ClientConfig{OurAddr: addr1, OurMAC: mac1, NDPCache: 2}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := h2.Configure(ClientConfig{OurAddr: addr2, OurMAC: mac2, NDPCache: 2}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var buf [64]byte
|
|
|
|
// No pending work: both clients should be silent.
|
|
n, err := h1.Encapsulate(buf[:], -1, 0)
|
|
if err != nil || n > 0 {
|
|
t.Fatal("expected no data before query:", err, n)
|
|
}
|
|
n, err = h2.Encapsulate(buf[:], -1, 0)
|
|
if err != nil || n > 0 {
|
|
t.Fatal("expected no data before query:", err, n)
|
|
}
|
|
|
|
// h1 queries h2's MAC.
|
|
if err = h1.NDPStartQuery(addr2, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// h1 sends a Neighbor Solicitation.
|
|
n, err = h1.Encapsulate(buf[:], -1, 0)
|
|
if err != nil {
|
|
t.Fatal("h1 encapsulate NS:", err)
|
|
} else if n == 0 {
|
|
t.Fatal("expected NS to be written")
|
|
}
|
|
validateNDP(t, buf[:n], TypeNeighborSolicitation)
|
|
|
|
// Verify NS target address is addr2.
|
|
ifrm, _ := NewFrame(buf[:n])
|
|
nsfrm := FrameNeighborSolicitation{Frame: ifrm}
|
|
if *nsfrm.TargetAddr() != addr2 {
|
|
t.Errorf("NS target addr mismatch: want %x, got %x", addr2, *nsfrm.TargetAddr())
|
|
}
|
|
|
|
// h2 receives the NS.
|
|
if err = h2.Demux(buf[:n], 0); err != nil {
|
|
t.Fatal("h2 demux NS:", err)
|
|
}
|
|
|
|
// h2 sends a Neighbor Advertisement.
|
|
n, err = h2.Encapsulate(buf[:], -1, 0)
|
|
if err != nil {
|
|
t.Fatal("h2 encapsulate NA:", err)
|
|
} else if n == 0 {
|
|
t.Fatal("expected NA to be written")
|
|
}
|
|
validateNDP(t, buf[:n], TypeNeighborAdvertisement)
|
|
|
|
// Verify NA target address is addr2 (h2's own address).
|
|
ifrm, _ = NewFrame(buf[:n])
|
|
nafrm := FrameNeighborAdvertisement{Frame: ifrm}
|
|
if *nafrm.TargetAddr() != addr2 {
|
|
t.Errorf("NA target addr mismatch: want %x, got %x", addr2, *nafrm.TargetAddr())
|
|
}
|
|
_, solicited, _ := nafrm.Flags()
|
|
if !solicited {
|
|
t.Error("expected solicited flag set in NA")
|
|
}
|
|
|
|
// Double-tap: h2 should have nothing left to send.
|
|
n2, err := h2.Encapsulate(buf[:], -1, 0)
|
|
if err != nil || n2 > 0 {
|
|
t.Fatal("double tap: expected no more data from h2:", err, n2)
|
|
}
|
|
|
|
// h1 receives the NA and resolves h2's MAC.
|
|
if err = h1.Demux(buf[:n], 0); err != nil {
|
|
t.Fatal("h1 demux NA:", err)
|
|
}
|
|
mac, err := h1.NDPCacheLookup(addr2)
|
|
if err != nil {
|
|
t.Fatal("cache lookup after resolution:", err)
|
|
}
|
|
if !bytes.Equal(mac[:], mac2[:]) {
|
|
t.Errorf("resolved MAC mismatch: want %x, got %x", mac2, mac)
|
|
}
|
|
|
|
// h1 should have nothing left to send.
|
|
n, err = h1.Encapsulate(buf[:], -1, 0)
|
|
if err != nil || n > 0 {
|
|
t.Fatal("expected no data after completion:", err, n)
|
|
}
|
|
}
|
|
|
|
func validateNDP(t *testing.T, buf []byte, wantType Type) {
|
|
t.Helper()
|
|
if len(buf) < sizeNDP {
|
|
t.Errorf("NDP frame too short: %d < %d", len(buf), sizeNDP)
|
|
return
|
|
}
|
|
ifrm, err := NewFrame(buf)
|
|
if err != nil {
|
|
t.Error("NewFrame:", err)
|
|
return
|
|
}
|
|
if ifrm.Type() != wantType {
|
|
t.Errorf("type mismatch: want %s, got %s", wantType, ifrm.Type())
|
|
}
|
|
if ifrm.Code() != 0 {
|
|
t.Errorf("code must be zero, got %d", ifrm.Code())
|
|
}
|
|
}
|