dhcp4d: send replies as unicast using raw sockets
Preferring unicast over multicast (which hogs a lot of airtime on WiFi networks) is a best practice. Some device/access point vendor combinations even seem to entirely eat (some?) broadcast traffic (sometimes), e.g. my Apple iPhone SE/Ubiquiti UAP-AC-HD, so that using unicast is required for reliable WiFi.
This commit is contained in:
parent
301d4c0d00
commit
3ba84074c7
@ -39,7 +39,7 @@ func logic() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
errs := make(chan error)
|
errs := make(chan error)
|
||||||
handler, err := dhcp4d.NewHandler("/perm")
|
handler, err := dhcp4d.NewHandler("/perm", nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,15 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"router7/internal/netconfig"
|
"router7/internal/netconfig"
|
||||||
|
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
"github.com/krolaw/dhcp4"
|
"github.com/krolaw/dhcp4"
|
||||||
|
"github.com/mdlayher/raw"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Lease struct {
|
type Lease struct {
|
||||||
@ -33,6 +37,8 @@ type Handler struct {
|
|||||||
options dhcp4.Options
|
options dhcp4.Options
|
||||||
leasesHW map[string]*Lease
|
leasesHW map[string]*Lease
|
||||||
leasesIP map[int]*Lease
|
leasesIP map[int]*Lease
|
||||||
|
rawConn net.PacketConn
|
||||||
|
iface *net.Interface
|
||||||
|
|
||||||
timeNow func() time.Time
|
timeNow func() time.Time
|
||||||
|
|
||||||
@ -40,16 +46,30 @@ type Handler struct {
|
|||||||
Leases func([]*Lease)
|
Leases func([]*Lease)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(dir string) (*Handler, error) {
|
func NewHandler(dir string, iface *net.Interface, conn net.PacketConn) (*Handler, error) {
|
||||||
serverIP, err := netconfig.LinkAddress(dir, "lan0")
|
serverIP, err := netconfig.LinkAddress(dir, "lan0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if iface == nil {
|
||||||
|
iface, err = net.InterfaceByName("lan0")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if conn == nil {
|
||||||
|
conn, err = raw.ListenPacket(iface, syscall.ETH_P_ALL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
serverIP = serverIP.To4()
|
serverIP = serverIP.To4()
|
||||||
start := make(net.IP, len(serverIP))
|
start := make(net.IP, len(serverIP))
|
||||||
copy(start, serverIP)
|
copy(start, serverIP)
|
||||||
start[len(start)-1] += 1
|
start[len(start)-1] += 1
|
||||||
return &Handler{
|
return &Handler{
|
||||||
|
rawConn: conn,
|
||||||
|
iface: iface,
|
||||||
leasesHW: make(map[string]*Lease),
|
leasesHW: make(map[string]*Lease),
|
||||||
leasesIP: make(map[int]*Lease),
|
leasesIP: make(map[int]*Lease),
|
||||||
serverIP: serverIP,
|
serverIP: serverIP,
|
||||||
@ -122,8 +142,47 @@ func (h *Handler) canLease(reqIP net.IP, hwaddr string) int {
|
|||||||
return -1 // lease unavailable
|
return -1 // lease unavailable
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: is ServeDHCP always run from the same goroutine, or do we need locking?
|
|
||||||
func (h *Handler) ServeDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options dhcp4.Options) dhcp4.Packet {
|
func (h *Handler) ServeDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options dhcp4.Options) dhcp4.Packet {
|
||||||
|
reply := h.serveDHCP(p, msgType, options)
|
||||||
|
buf := gopacket.NewSerializeBuffer()
|
||||||
|
opts := gopacket.SerializeOptions{
|
||||||
|
ComputeChecksums: true,
|
||||||
|
FixLengths: true,
|
||||||
|
}
|
||||||
|
ethernet := &layers.Ethernet{
|
||||||
|
DstMAC: p.CHAddr(),
|
||||||
|
SrcMAC: h.iface.HardwareAddr,
|
||||||
|
EthernetType: layers.EthernetTypeIPv4,
|
||||||
|
}
|
||||||
|
|
||||||
|
ip := &layers.IPv4{
|
||||||
|
Version: 4,
|
||||||
|
TTL: 255,
|
||||||
|
SrcIP: h.serverIP,
|
||||||
|
DstIP: reply.YIAddr(),
|
||||||
|
Protocol: layers.IPProtocolUDP,
|
||||||
|
Flags: layers.IPv4DontFragment,
|
||||||
|
}
|
||||||
|
udp := &layers.UDP{
|
||||||
|
SrcPort: 67,
|
||||||
|
DstPort: 68,
|
||||||
|
}
|
||||||
|
udp.SetNetworkLayerForChecksum(ip)
|
||||||
|
gopacket.SerializeLayers(buf, opts,
|
||||||
|
ethernet,
|
||||||
|
ip,
|
||||||
|
udp,
|
||||||
|
gopacket.Payload(reply))
|
||||||
|
|
||||||
|
if _, err := h.rawConn.WriteTo(buf.Bytes(), &raw.Addr{p.CHAddr()}); err != nil {
|
||||||
|
log.Printf("WriteTo: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: is ServeDHCP always run from the same goroutine, or do we need locking?
|
||||||
|
func (h *Handler) serveDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options dhcp4.Options) dhcp4.Packet {
|
||||||
reqIP := net.IP(options[dhcp4.OptionRequestedIPAddress])
|
reqIP := net.IP(options[dhcp4.OptionRequestedIPAddress])
|
||||||
if reqIP == nil {
|
if reqIP == nil {
|
||||||
reqIP = net.IP(p.CIAddr())
|
reqIP = net.IP(p.CIAddr())
|
||||||
@ -153,14 +212,12 @@ func (h *Handler) ServeDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options d
|
|||||||
return nil // no free leases
|
return nil // no free leases
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt := dhcp4.ReplyPacket(p,
|
return dhcp4.ReplyPacket(p,
|
||||||
dhcp4.Offer,
|
dhcp4.Offer,
|
||||||
h.serverIP,
|
h.serverIP,
|
||||||
dhcp4.IPAdd(h.start, free),
|
dhcp4.IPAdd(h.start, free),
|
||||||
h.leasePeriod,
|
h.leasePeriod,
|
||||||
h.options.SelectOrderOrAll(options[dhcp4.OptionParameterRequestList]))
|
h.options.SelectOrderOrAll(options[dhcp4.OptionParameterRequestList]))
|
||||||
pkt.SetBroadcast(true)
|
|
||||||
return pkt
|
|
||||||
|
|
||||||
case dhcp4.Request:
|
case dhcp4.Request:
|
||||||
if server, ok := options[dhcp4.OptionServerIdentifier]; ok && !net.IP(server).Equal(h.serverIP) {
|
if server, ok := options[dhcp4.OptionServerIdentifier]; ok && !net.IP(server).Equal(h.serverIP) {
|
||||||
@ -193,6 +250,7 @@ func (h *Handler) ServeDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options d
|
|||||||
|
|
||||||
h.leasesIP[leaseNum] = lease
|
h.leasesIP[leaseNum] = lease
|
||||||
h.leasesHW[lease.HardwareAddr] = lease
|
h.leasesHW[lease.HardwareAddr] = lease
|
||||||
|
log.Printf("handed out lease %+v (ip bytes: %#v)", lease, lease.Addr)
|
||||||
if h.Leases != nil {
|
if h.Leases != nil {
|
||||||
var leases []*Lease
|
var leases []*Lease
|
||||||
for _, l := range h.leasesIP {
|
for _, l := range h.leasesIP {
|
||||||
@ -202,7 +260,6 @@ func (h *Handler) ServeDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options d
|
|||||||
}
|
}
|
||||||
return dhcp4.ReplyPacket(p, dhcp4.ACK, h.serverIP, reqIP, h.leasePeriod,
|
return dhcp4.ReplyPacket(p, dhcp4.ACK, h.serverIP, reqIP, h.leasePeriod,
|
||||||
h.options.SelectOrderOrAll(options[dhcp4.OptionParameterRequestList]))
|
h.options.SelectOrderOrAll(options[dhcp4.OptionParameterRequestList]))
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,16 @@ const goldenInterfaces = `
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
type noopSink struct{}
|
||||||
|
|
||||||
|
func (*noopSink) LocalAddr() net.Addr { return nil }
|
||||||
|
func (*noopSink) Close() error { return nil }
|
||||||
|
func (*noopSink) WriteTo(b []byte, addr net.Addr) (n int, err error) { return len(b), nil }
|
||||||
|
func (*noopSink) SetDeadline(t time.Time) error { return nil }
|
||||||
|
func (*noopSink) SetReadDeadline(t time.Time) error { return nil }
|
||||||
|
func (*noopSink) SetWriteDeadline(t time.Time) error { return nil }
|
||||||
|
func (*noopSink) ReadFrom(buf []byte) (int, net.Addr, error) { return 0, nil, nil }
|
||||||
|
|
||||||
func testHandler(t *testing.T) (_ *Handler, cleanup func()) {
|
func testHandler(t *testing.T) (_ *Handler, cleanup func()) {
|
||||||
tmpdir, err := ioutil.TempDir("", "dhcp4dtest")
|
tmpdir, err := ioutil.TempDir("", "dhcp4dtest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -55,7 +65,13 @@ func testHandler(t *testing.T) (_ *Handler, cleanup func()) {
|
|||||||
if err := ioutil.WriteFile(filepath.Join(tmpdir, "interfaces.json"), []byte(goldenInterfaces), 0644); err != nil {
|
if err := ioutil.WriteFile(filepath.Join(tmpdir, "interfaces.json"), []byte(goldenInterfaces), 0644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
handler, err := NewHandler(tmpdir)
|
handler, err := NewHandler(
|
||||||
|
tmpdir,
|
||||||
|
&net.Interface{
|
||||||
|
HardwareAddr: net.HardwareAddr([]byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}),
|
||||||
|
},
|
||||||
|
&noopSink{},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -100,7 +116,7 @@ func TestLease(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
if !leasedCalled {
|
if !leasedCalled {
|
||||||
t.Fatalf("leased callback not called")
|
t.Fatalf("leased callback not called")
|
||||||
}
|
}
|
||||||
@ -118,7 +134,7 @@ func TestPreferredAddress(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("no requested IP", func(t *testing.T) {
|
t.Run("no requested IP", func(t *testing.T) {
|
||||||
p := request(net.IPv4zero, hardwareAddr)
|
p := request(net.IPv4zero, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Discover, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Discover, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr.To4(); bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr.To4(); bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
@ -126,7 +142,7 @@ func TestPreferredAddress(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("requested CIAddr", func(t *testing.T) {
|
t.Run("requested CIAddr", func(t *testing.T) {
|
||||||
p := request(addr, hardwareAddr)
|
p := request(addr, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Discover, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Discover, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
@ -151,7 +167,7 @@ func TestPreferredAddress(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Discover, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Discover, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
@ -170,7 +186,7 @@ func TestPoolBoundaries(t *testing.T) {
|
|||||||
for _, last := range []byte{1, 242} {
|
for _, last := range []byte{1, 242} {
|
||||||
addr[len(addr)-1] = last
|
addr[len(addr)-1] = last
|
||||||
p := request(addr, hardwareAddr)
|
p := request(addr, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
opts := resp.ParseOptions()
|
opts := resp.ParseOptions()
|
||||||
if got, want := dhcp4.MessageType(opts[dhcp4.OptionDHCPMessageType][0]), dhcp4.NAK; got != want {
|
if got, want := dhcp4.MessageType(opts[dhcp4.OptionDHCPMessageType][0]), dhcp4.NAK; got != want {
|
||||||
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
|
||||||
@ -191,34 +207,34 @@ func TestPreviousLease(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
p := request(addr1, hardwareAddr1)
|
p := request(addr1, hardwareAddr1)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr1.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr1.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
p = request(addr1, hardwareAddr2)
|
p = request(addr1, hardwareAddr2)
|
||||||
resp = handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp = handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
opts := resp.ParseOptions()
|
opts := resp.ParseOptions()
|
||||||
if got, want := dhcp4.MessageType(opts[dhcp4.OptionDHCPMessageType][0]), dhcp4.NAK; got != want {
|
if got, want := dhcp4.MessageType(opts[dhcp4.OptionDHCPMessageType][0]), dhcp4.NAK; got != want {
|
||||||
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
p = discover(net.IPv4zero, hardwareAddr1)
|
p = discover(net.IPv4zero, hardwareAddr1)
|
||||||
resp = handler.ServeDHCP(p, dhcp4.Discover, p.ParseOptions())
|
resp = handler.serveDHCP(p, dhcp4.Discover, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr1.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr1.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free addr1 by requesting addr2
|
// Free addr1 by requesting addr2
|
||||||
p = request(addr2, hardwareAddr1)
|
p = request(addr2, hardwareAddr1)
|
||||||
resp = handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp = handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr2.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr2.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify addr1 is now available to other clients
|
// Verify addr1 is now available to other clients
|
||||||
p = request(addr1, hardwareAddr2)
|
p = request(addr1, hardwareAddr2)
|
||||||
resp = handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp = handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr1.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr1.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
@ -244,7 +260,7 @@ func TestPermanentLease(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
p := request(addr, hardwareAddr)
|
p := request(addr, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
@ -254,7 +270,7 @@ func TestPermanentLease(t *testing.T) {
|
|||||||
hardwareAddr[len(hardwareAddr)-1] = 0x77
|
hardwareAddr[len(hardwareAddr)-1] = 0x77
|
||||||
|
|
||||||
p = request(addr, hardwareAddr)
|
p = request(addr, hardwareAddr)
|
||||||
resp = handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp = handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
opts := resp.ParseOptions()
|
opts := resp.ParseOptions()
|
||||||
if got, want := dhcp4.MessageType(opts[dhcp4.OptionDHCPMessageType][0]), dhcp4.NAK; got != want {
|
if got, want := dhcp4.MessageType(opts[dhcp4.OptionDHCPMessageType][0]), dhcp4.NAK; got != want {
|
||||||
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
|
||||||
@ -278,7 +294,7 @@ func TestExpiration(t *testing.T) {
|
|||||||
addr[len(addr)-1] = byte(1 + (i % 254)) // avoid .0 (net) and .255 (broadcast)
|
addr[len(addr)-1] = byte(1 + (i % 254)) // avoid .0 (net) and .255 (broadcast)
|
||||||
hardwareAddr[len(hardwareAddr)-1] = addr[len(addr)-1]
|
hardwareAddr[len(hardwareAddr)-1] = addr[len(addr)-1]
|
||||||
p := request(addr, hardwareAddr)
|
p := request(addr, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
@ -291,7 +307,7 @@ func TestExpiration(t *testing.T) {
|
|||||||
addr[len(addr)-1] = byte(1 + (i % 254)) // avoid .0 (net) and .255 (broadcast)
|
addr[len(addr)-1] = byte(1 + (i % 254)) // avoid .0 (net) and .255 (broadcast)
|
||||||
hardwareAddr[len(hardwareAddr)-1] = addr[len(addr)-1]
|
hardwareAddr[len(hardwareAddr)-1] = addr[len(addr)-1]
|
||||||
p := request(addr, hardwareAddr)
|
p := request(addr, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
@ -304,7 +320,7 @@ func TestExpiration(t *testing.T) {
|
|||||||
addr[len(addr)-1] = byte(1 + (i % 254)) // avoid .0 (net) and .255 (broadcast)
|
addr[len(addr)-1] = byte(1 + (i % 254)) // avoid .0 (net) and .255 (broadcast)
|
||||||
hardwareAddr[len(hardwareAddr)-1] = addr[len(addr)-1] - 1
|
hardwareAddr[len(hardwareAddr)-1] = addr[len(addr)-1] - 1
|
||||||
p := request(addr, hardwareAddr)
|
p := request(addr, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
opts := resp.ParseOptions()
|
opts := resp.ParseOptions()
|
||||||
if got, want := dhcp4.MessageType(opts[dhcp4.OptionDHCPMessageType][0]), dhcp4.NAK; got != want {
|
if got, want := dhcp4.MessageType(opts[dhcp4.OptionDHCPMessageType][0]), dhcp4.NAK; got != want {
|
||||||
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
|
||||||
@ -313,7 +329,7 @@ func TestExpiration(t *testing.T) {
|
|||||||
|
|
||||||
hardwareAddr[len(hardwareAddr)-1] = 0
|
hardwareAddr[len(hardwareAddr)-1] = 0
|
||||||
p := discover(addr, hardwareAddr)
|
p := discover(addr, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Discover, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Discover, p.ParseOptions())
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
t.Errorf("DHCPDISCOVER(%v) resulted in unexpected offer of %v", addr, resp.YIAddr())
|
t.Errorf("DHCPDISCOVER(%v) resulted in unexpected offer of %v", addr, resp.YIAddr())
|
||||||
}
|
}
|
||||||
@ -326,7 +342,7 @@ func TestExpiration(t *testing.T) {
|
|||||||
for i := 1; i < 1+230; i++ {
|
for i := 1; i < 1+230; i++ {
|
||||||
addr[len(addr)-1] = byte(1 + (i % 254)) // avoid .0 (net) and .255 (broadcast)
|
addr[len(addr)-1] = byte(1 + (i % 254)) // avoid .0 (net) and .255 (broadcast)
|
||||||
p := request(addr, hardwareAddr)
|
p := request(addr, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPREQUEST resulted in wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
@ -347,7 +363,7 @@ func TestServerID(t *testing.T) {
|
|||||||
Code: dhcp4.OptionServerIdentifier,
|
Code: dhcp4.OptionServerIdentifier,
|
||||||
Value: net.IP{192, 168, 1, 1},
|
Value: net.IP{192, 168, 1, 1},
|
||||||
})
|
})
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Request, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
t.Errorf("DHCPDISCOVER(%v) resulted in unexpected offer of %v", addr, resp.YIAddr())
|
t.Errorf("DHCPDISCOVER(%v) resulted in unexpected offer of %v", addr, resp.YIAddr())
|
||||||
}
|
}
|
||||||
@ -371,7 +387,7 @@ func TestPersistentStorage(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
p := request(net.IPv4zero, hardwareAddr)
|
p := request(net.IPv4zero, hardwareAddr)
|
||||||
resp := handler.ServeDHCP(p, dhcp4.Discover, p.ParseOptions())
|
resp := handler.serveDHCP(p, dhcp4.Discover, p.ParseOptions())
|
||||||
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
|
||||||
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user