+ dhcp: use ICMP for IP conflict detection
+ 'icmp_timeout_msec' YAML config setting
This commit is contained in:
parent
542a67b84e
commit
8fa2f48136
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/krolaw/dhcp4"
|
"github.com/krolaw/dhcp4"
|
||||||
|
"github.com/sparrc/go-ping"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultDiscoverTime = time.Second * 3
|
const defaultDiscoverTime = time.Second * 3
|
||||||
|
@ -33,6 +34,10 @@ type ServerConfig struct {
|
||||||
RangeStart string `json:"range_start" yaml:"range_start"`
|
RangeStart string `json:"range_start" yaml:"range_start"`
|
||||||
RangeEnd string `json:"range_end" yaml:"range_end"`
|
RangeEnd string `json:"range_end" yaml:"range_end"`
|
||||||
LeaseDuration uint `json:"lease_duration" yaml:"lease_duration"` // in seconds
|
LeaseDuration uint `json:"lease_duration" yaml:"lease_duration"` // in seconds
|
||||||
|
|
||||||
|
// IP conflict detector: time (ms) to wait for ICMP reply.
|
||||||
|
// 0: disable
|
||||||
|
ICMPTimeout uint `json:"icmp_timeout_msec" yaml:"icmp_timeout_msec"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server - the current state of the DHCP server
|
// Server - the current state of the DHCP server
|
||||||
|
@ -325,6 +330,51 @@ func (s *Server) ServeDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options dh
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send ICMP to the specified machine
|
||||||
|
// Return TRUE if it doesn't reply, which probably means that the IP is available
|
||||||
|
func (s *Server) addrAvailable(target net.IP) bool {
|
||||||
|
|
||||||
|
if s.ICMPTimeout == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
pinger, err := ping.NewPinger(target.String())
|
||||||
|
if err != nil {
|
||||||
|
log.Error("ping.NewPinger(): %v", err)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
pinger.SetPrivileged(true)
|
||||||
|
pinger.Timeout = time.Duration(s.ICMPTimeout) * time.Millisecond
|
||||||
|
pinger.Count = 1
|
||||||
|
reply := false
|
||||||
|
pinger.OnRecv = func(pkt *ping.Packet) {
|
||||||
|
// log.Tracef("Received ICMP Reply from %v", target)
|
||||||
|
reply = true
|
||||||
|
}
|
||||||
|
log.Tracef("Sending ICMP Echo to %v", target)
|
||||||
|
pinger.Run()
|
||||||
|
|
||||||
|
if reply {
|
||||||
|
log.Info("DHCP: IP conflict: %v is already used by another device", target)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Tracef("ICMP procedure is complete: %v", target)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the specified IP to the black list for a time period
|
||||||
|
func (s *Server) blacklistLease(lease *Lease) {
|
||||||
|
hw := make(net.HardwareAddr, 6)
|
||||||
|
s.reserveIP(lease.IP, hw)
|
||||||
|
s.Lock()
|
||||||
|
lease.HWAddr = hw
|
||||||
|
lease.Hostname = ""
|
||||||
|
lease.Expiry = time.Now().Add(s.leaseTime)
|
||||||
|
s.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// Return TRUE if DHCP packet is correct
|
// Return TRUE if DHCP packet is correct
|
||||||
func isValidPacket(p dhcp4.Packet) bool {
|
func isValidPacket(p dhcp4.Packet) bool {
|
||||||
hw := p.CHAddr()
|
hw := p.CHAddr()
|
||||||
|
@ -358,6 +408,12 @@ func (s *Server) handleDiscover(p dhcp4.Packet, options dhcp4.Options) dhcp4.Pac
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !s.addrAvailable(lease.IP) {
|
||||||
|
s.blacklistLease(lease)
|
||||||
|
lease = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -17,6 +17,7 @@ require (
|
||||||
github.com/miekg/dns v1.1.1
|
github.com/miekg/dns v1.1.1
|
||||||
github.com/shirou/gopsutil v2.18.10+incompatible
|
github.com/shirou/gopsutil v2.18.10+incompatible
|
||||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
|
||||||
|
github.com/sparrc/go-ping v0.0.0-20181106165434-ef3ab45e41b0
|
||||||
github.com/stretchr/testify v1.2.2
|
github.com/stretchr/testify v1.2.2
|
||||||
go.uber.org/goleak v0.10.0
|
go.uber.org/goleak v0.10.0
|
||||||
golang.org/x/net v0.0.0-20190119204137-ed066c81e75e
|
golang.org/x/net v0.0.0-20190119204137-ed066c81e75e
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -56,6 +56,8 @@ github.com/shirou/gopsutil v2.18.10+incompatible h1:cy84jW6EVRPa5g9HAHrlbxMSIjBh
|
||||||
github.com/shirou/gopsutil v2.18.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v2.18.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=
|
||||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||||
|
github.com/sparrc/go-ping v0.0.0-20181106165434-ef3ab45e41b0 h1:mu7brOsdaH5Dqf93vdch+mr/0To8Sgc+yInt/jE/RJM=
|
||||||
|
github.com/sparrc/go-ping v0.0.0-20181106165434-ef3ab45e41b0/go.mod h1:eMyUVp6f/5jnzM+3zahzl7q6UXLbgSc3MKg/+ow9QW0=
|
||||||
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
|
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
|
||||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
|
|
Loading…
Reference in New Issue