mirror of
https://github.com/soypat/lneto.git
synced 2026-07-26 10:38:47 +00:00
aa77403a2b
* begin working on arp cache * fix little things * rework arp cache priority * fix test * keep working on ARP * push changes before thinking about ip prefix issue * add passive peer MAC setting * patch egress mac with correct ethernet CRCs * consolidate subnet learning in subnetTable type * add tests and fix subnet table bug
121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
package arp
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
|
|
"github.com/soypat/lneto"
|
|
"github.com/soypat/lneto/ethernet"
|
|
)
|
|
|
|
func TestHandler(t *testing.T) {
|
|
var c1, c2 Handler
|
|
err := c1.Reset(HandlerConfig{
|
|
HardwareAddr: []byte{0xde, 0xad, 0xbe, 0xef, 0x00, 0x00},
|
|
ProtocolAddr: []byte{192, 168, 1, 1},
|
|
MaxQueries: 1,
|
|
MaxPending: 1,
|
|
HardwareType: 1,
|
|
ProtocolType: ethernet.TypeIPv4,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = c2.Reset(HandlerConfig{
|
|
HardwareAddr: []byte{0xc0, 0xff, 0xee, 0xc0, 0xff, 0xee},
|
|
ProtocolAddr: []byte{192, 168, 1, 2},
|
|
MaxQueries: 1,
|
|
MaxPending: 1,
|
|
HardwareType: 1,
|
|
ProtocolType: ethernet.TypeIPv4,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var buf, discard [64]byte
|
|
n, err := c1.Encapsulate(buf[:], -1, 0)
|
|
if err != nil {
|
|
t.Fatal("error on should be nop send:", err)
|
|
} else if n > 0 {
|
|
t.Fatal("should not send if no query")
|
|
}
|
|
n, err = c2.Encapsulate(buf[:], -1, 0)
|
|
if err != nil {
|
|
t.Fatal("error on should be nop send:", err)
|
|
} else if n > 0 {
|
|
t.Fatal("should not send if no query")
|
|
}
|
|
|
|
// Perform ARP exchange.
|
|
expectHWAddr := c2.ourHWAddr[:]
|
|
queryAddr := c2.ourProtoAddr
|
|
err = c1.StartQuery(queryAddr, false)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
n, err = c1.Encapsulate(buf[:], -1, 0) // Send Request.
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
} else if n == 0 {
|
|
t.Fatal("expected send of data after first query")
|
|
}
|
|
validateARP(t, buf[:])
|
|
err = c2.Demux(buf[:n], 0) // Receive request.
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
n, err = c2.Encapsulate(buf[:], -1, 0) // Send response.
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
} else if n == 0 {
|
|
t.Fatal("got no response to request")
|
|
}
|
|
validateARP(t, buf[:])
|
|
n, err = c2.Encapsulate(discard[:], -1, 0) // Double tap check, should send nothing.
|
|
if err != nil {
|
|
t.Fatal("double tap send error:", err)
|
|
} else if n > 0 {
|
|
t.Fatal("wanted no data sent after response sent")
|
|
}
|
|
|
|
err = c1.Demux(buf[:], 0) // Receive response.
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
hwaddr, err := c1.CacheLookup(queryAddr)
|
|
if err != nil {
|
|
t.Fatal("expected query result:", err)
|
|
} else if !bytes.Equal(hwaddr, expectHWAddr) {
|
|
t.Fatalf("expected to get hwaddr %x!=%x", hwaddr, expectHWAddr)
|
|
}
|
|
n, err = c1.Encapsulate(buf[:], -1, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
} else if n > 0 {
|
|
t.Fatal("expected no data")
|
|
}
|
|
n, err = c2.Encapsulate(buf[:], -1, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
} else if n > 0 {
|
|
t.Fatal("expected no data")
|
|
}
|
|
}
|
|
|
|
func validateARP(t *testing.T, buf []byte) {
|
|
t.Helper()
|
|
afrm, err := NewFrame(buf)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
var vld lneto.Validator
|
|
afrm.ValidateSize(&vld)
|
|
if vld.HasError() {
|
|
t.Errorf("invalid arp: %s", vld.ErrPop())
|
|
} else if err := vld.ErrPop(); err != nil {
|
|
panic("unreachable: " + err.Error())
|
|
}
|
|
}
|