mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-11-24 14:05:45 +03:00
cleanup
This commit is contained in:
parent
917f20fe1c
commit
8f9353782b
7 changed files with 164 additions and 324 deletions
|
@ -127,7 +127,8 @@ func normalizeLeases(staticLeases, dynLeases []*Lease) []*Lease {
|
||||||
func (s *Server) dbStore() {
|
func (s *Server) dbStore() {
|
||||||
var leases []leaseJSON
|
var leases []leaseJSON
|
||||||
|
|
||||||
for _, l := range s.srv4.leases {
|
leases4 := s.srv4.GetLeasesRef()
|
||||||
|
for _, l := range leases4 {
|
||||||
if l.Expiry.Unix() == 0 {
|
if l.Expiry.Unix() == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,8 @@ func (s *Server) dbStore() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.srv6 != nil {
|
if s.srv6 != nil {
|
||||||
for _, l := range s.srv6.leases {
|
leases6 := s.srv6.GetLeasesRef()
|
||||||
|
for _, l := range leases6 {
|
||||||
if l.Expiry.Unix() == 0 {
|
if l.Expiry.Unix() == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
package dhcpd
|
package dhcpd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
|
@ -58,18 +56,6 @@ const (
|
||||||
|
|
||||||
// Server - the current state of the DHCP server
|
// Server - the current state of the DHCP server
|
||||||
type Server struct {
|
type Server struct {
|
||||||
// conn *filterConn // listening UDP socket
|
|
||||||
|
|
||||||
// ipnet *net.IPNet // if interface name changes, this needs to be reset
|
|
||||||
|
|
||||||
// cond *sync.Cond // Synchronize worker thread with main thread
|
|
||||||
// mutex sync.Mutex // Mutex for 'cond'
|
|
||||||
// running bool // Set if the worker thread is running
|
|
||||||
// stopping bool // Set if the worker thread should be stopped
|
|
||||||
|
|
||||||
// leases
|
|
||||||
// leaseOptions dhcp4.Options // parsed from config GatewayIP and SubnetMask
|
|
||||||
|
|
||||||
srv4 *V4Server
|
srv4 *V4Server
|
||||||
srv6 *V6Server
|
srv6 *V6Server
|
||||||
|
|
||||||
|
@ -79,16 +65,6 @@ type Server struct {
|
||||||
onLeaseChanged onLeaseChangedT
|
onLeaseChanged onLeaseChangedT
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print information about the available network interfaces
|
|
||||||
func printInterfaces() {
|
|
||||||
ifaces, _ := net.Interfaces()
|
|
||||||
var buf strings.Builder
|
|
||||||
for i := range ifaces {
|
|
||||||
buf.WriteString(fmt.Sprintf("\"%s\", ", ifaces[i].Name))
|
|
||||||
}
|
|
||||||
log.Info("Available network interfaces: %s", buf.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckConfig checks the configuration
|
// CheckConfig checks the configuration
|
||||||
func (s *Server) CheckConfig(config ServerConfig) error {
|
func (s *Server) CheckConfig(config ServerConfig) error {
|
||||||
return nil
|
return nil
|
||||||
|
@ -194,16 +170,15 @@ func (s *Server) Leases(flags int) []Lease {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddStaticLease adds a static lease (thread-safe)
|
||||||
|
func (s *Server) AddStaticLease(lease Lease) error {
|
||||||
|
return s.srv4.AddStaticLease(lease)
|
||||||
|
}
|
||||||
|
|
||||||
// FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases
|
// FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases
|
||||||
func (s *Server) FindMACbyIP(ip net.IP) net.HardwareAddr {
|
func (s *Server) FindMACbyIP(ip net.IP) net.HardwareAddr {
|
||||||
if ip.To4() != nil {
|
if ip.To4() != nil {
|
||||||
return s.srv4.FindMACbyIP4(ip)
|
return s.srv4.FindMACbyIP(ip)
|
||||||
}
|
}
|
||||||
return s.srv6.FindMACbyIP6(ip)
|
return s.srv6.FindMACbyIP(ip)
|
||||||
}
|
|
||||||
|
|
||||||
// Reset internal state
|
|
||||||
func (s *Server) reset() {
|
|
||||||
s.srv4.Reset()
|
|
||||||
s.srv6.Reset()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ func TestDB(t *testing.T) {
|
||||||
|
|
||||||
_ = os.Remove("leases.db")
|
_ = os.Remove("leases.db")
|
||||||
s.dbStore()
|
s.dbStore()
|
||||||
s.reset()
|
s.srv4.Reset()
|
||||||
|
|
||||||
s.dbLoad()
|
s.dbLoad()
|
||||||
|
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
package dhcpd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/joomcode/errorx"
|
|
||||||
"golang.org/x/net/ipv4"
|
|
||||||
)
|
|
||||||
|
|
||||||
// filterConn listens to 0.0.0.0:67, but accepts packets only from specific interface
|
|
||||||
// This is necessary for DHCP daemon to work, since binding to IP address doesn't
|
|
||||||
// us access to see Discover/Request packets from clients.
|
|
||||||
//
|
|
||||||
// TODO: on windows, controlmessage does not work, try to find out another way
|
|
||||||
// https://github.com/golang/net/blob/master/ipv4/payload.go#L13
|
|
||||||
type filterConn struct {
|
|
||||||
iface net.Interface
|
|
||||||
conn *ipv4.PacketConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFilterConn(iface net.Interface, address string) (*filterConn, error) {
|
|
||||||
c, err := net.ListenPacket("udp4", address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errorx.Decorate(err, "Couldn't listen to %s on UDP4", address)
|
|
||||||
}
|
|
||||||
|
|
||||||
p := ipv4.NewPacketConn(c)
|
|
||||||
err = p.SetControlMessage(ipv4.FlagInterface, true)
|
|
||||||
if err != nil {
|
|
||||||
c.Close()
|
|
||||||
return nil, errorx.Decorate(err, "Couldn't set control message FlagInterface on connection")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &filterConn{iface: iface, conn: p}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
|
||||||
for { // read until we find a suitable packet
|
|
||||||
n, cm, addr, err := f.conn.ReadFrom(b)
|
|
||||||
if err != nil {
|
|
||||||
return 0, addr, errorx.Decorate(err, "Error when reading from socket")
|
|
||||||
}
|
|
||||||
if cm == nil {
|
|
||||||
// no controlmessage was passed, so pass the packet to the caller
|
|
||||||
return n, addr, nil
|
|
||||||
}
|
|
||||||
if cm.IfIndex == f.iface.Index {
|
|
||||||
return n, addr, nil
|
|
||||||
}
|
|
||||||
// packet doesn't match criteria, drop it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
|
||||||
cm := ipv4.ControlMessage{
|
|
||||||
IfIndex: f.iface.Index,
|
|
||||||
}
|
|
||||||
return f.conn.WriteTo(b, &cm, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *filterConn) Close() error {
|
|
||||||
return f.conn.Close()
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/dhcpd"
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
|
||||||
"github.com/krolaw/dhcp4"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) < 2 {
|
|
||||||
log.Printf("Usage: %s <interface name>", os.Args[0])
|
|
||||||
os.Exit(64)
|
|
||||||
}
|
|
||||||
|
|
||||||
ifaceName := os.Args[1]
|
|
||||||
present, err := dhcpd.CheckIfOtherDHCPServersPresent(ifaceName)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
log.Printf("Found DHCP server? %v", present)
|
|
||||||
if present {
|
|
||||||
log.Printf("Will not start DHCP server because there's already running one on the network")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
iface, err := net.InterfaceByName(ifaceName)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// get ipv4 address of an interface
|
|
||||||
ifaceIPNet := getIfaceIPv4(iface)
|
|
||||||
if ifaceIPNet == nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// append 10 to server's IP address as start
|
|
||||||
start := dhcp4.IPAdd(ifaceIPNet.IP, 10)
|
|
||||||
// lease range is 100 IP's, but TODO: don't go beyond end of subnet mask
|
|
||||||
stop := dhcp4.IPAdd(start, 100)
|
|
||||||
|
|
||||||
server := dhcpd.Server{}
|
|
||||||
config := dhcpd.ServerConfig{
|
|
||||||
InterfaceName: ifaceName,
|
|
||||||
RangeStart: start.String(),
|
|
||||||
RangeEnd: stop.String(),
|
|
||||||
SubnetMask: "255.255.255.0",
|
|
||||||
GatewayIP: "192.168.7.1",
|
|
||||||
}
|
|
||||||
log.Printf("Starting DHCP server")
|
|
||||||
err = server.Init(config)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = server.Start()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
log.Printf("Stopping DHCP server")
|
|
||||||
err = server.Stop()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
log.Printf("Starting DHCP server")
|
|
||||||
err = server.Start()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
log.Printf("Starting DHCP server while it's already running")
|
|
||||||
err = server.Start()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
log.Printf("Now serving DHCP")
|
|
||||||
signalChannel := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
<-signalChannel
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// return first IPv4 address of an interface, if there is any
|
|
||||||
func getIfaceIPv4(iface *net.Interface) *net.IPNet {
|
|
||||||
ifaceAddrs, err := iface.Addrs()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, addr := range ifaceAddrs {
|
|
||||||
ipnet, ok := addr.(*net.IPNet)
|
|
||||||
if !ok {
|
|
||||||
// not an IPNet, should not happen
|
|
||||||
log.Fatalf("SHOULD NOT HAPPEN: got iface.Addrs() element %s that is not net.IPNet", addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ipnet.IP.To4() == nil {
|
|
||||||
log.Printf("Got IP that is not IPv4: %v", ipnet.IP)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Got IP that is IPv4: %v", ipnet.IP)
|
|
||||||
return &net.IPNet{
|
|
||||||
IP: ipnet.IP.To4(),
|
|
||||||
Mask: ipnet.Mask,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
248
dhcpd/v4.go
248
dhcpd/v4.go
|
@ -78,6 +78,11 @@ func (s *V4Server) ResetLeases(leases []*Lease) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLeasesRef - get leases
|
||||||
|
func (s *V4Server) GetLeasesRef() []*Lease {
|
||||||
|
return s.leases
|
||||||
|
}
|
||||||
|
|
||||||
// GetLeases returns the list of current DHCP leases (thread-safe)
|
// GetLeases returns the list of current DHCP leases (thread-safe)
|
||||||
func (s *V4Server) GetLeases(flags int) []Lease {
|
func (s *V4Server) GetLeases(flags int) []Lease {
|
||||||
var result []Lease
|
var result []Lease
|
||||||
|
@ -95,8 +100,8 @@ func (s *V4Server) GetLeases(flags int) []Lease {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindMACbyIP4 - find a MAC address by IP address in the currently active DHCP leases
|
// FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases
|
||||||
func (s *V4Server) FindMACbyIP4(ip net.IP) net.HardwareAddr {
|
func (s *V4Server) FindMACbyIP(ip net.IP) net.HardwareAddr {
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
|
|
||||||
s.leasesLock.Lock()
|
s.leasesLock.Lock()
|
||||||
|
@ -108,7 +113,7 @@ func (s *V4Server) FindMACbyIP4(ip net.IP) net.HardwareAddr {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range s.leases {
|
for _, l := range s.leases {
|
||||||
if l.IP.Equal(ip4) {
|
if net.IP.Equal(ip, ip4) {
|
||||||
unix := l.Expiry.Unix()
|
unix := l.Expiry.Unix()
|
||||||
if unix > now || unix == leaseExpireStatic {
|
if unix > now || unix == leaseExpireStatic {
|
||||||
return l.HWAddr
|
return l.HWAddr
|
||||||
|
@ -154,7 +159,7 @@ func (s *V4Server) rmDynamicLease(lease Lease) error {
|
||||||
l = s.leases[i]
|
l = s.leases[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes.Equal(l.IP, lease.IP) {
|
if net.IP.Equal(l.IP, lease.IP) {
|
||||||
|
|
||||||
if l.Expiry.Unix() == leaseExpireStatic {
|
if l.Expiry.Unix() == leaseExpireStatic {
|
||||||
return fmt.Errorf("static lease already exists")
|
return fmt.Errorf("static lease already exists")
|
||||||
|
@ -173,10 +178,10 @@ func (s *V4Server) addLease(l *Lease) {
|
||||||
log.Debug("DHCPv4: added lease %s <-> %s", l.IP, l.HWAddr)
|
log.Debug("DHCPv4: added lease %s <-> %s", l.IP, l.HWAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a lease with the same properies
|
// Remove a lease with the same properties
|
||||||
func (s *V4Server) rmLease(lease Lease) error {
|
func (s *V4Server) rmLease(lease Lease) error {
|
||||||
for i, l := range s.leases {
|
for i, l := range s.leases {
|
||||||
if bytes.Equal(l.IP, lease.IP) {
|
if net.IP.Equal(l.IP, lease.IP) {
|
||||||
|
|
||||||
if !bytes.Equal(l.HWAddr, lease.HWAddr) ||
|
if !bytes.Equal(l.HWAddr, lease.HWAddr) ||
|
||||||
l.Hostname != lease.Hostname {
|
l.Hostname != lease.Hostname {
|
||||||
|
@ -328,120 +333,146 @@ func (s *V4Server) reserveLease(mac net.HardwareAddr) *Lease {
|
||||||
return &l
|
return &l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process Discover request and return lease
|
||||||
|
func (s *V4Server) processDiscover(req *dhcpv4.DHCPv4, resp *dhcpv4.DHCPv4) *Lease {
|
||||||
|
mac := req.ClientHWAddr
|
||||||
|
|
||||||
|
s.leasesLock.Lock()
|
||||||
|
defer s.leasesLock.Unlock()
|
||||||
|
|
||||||
|
lease := s.findLease(mac)
|
||||||
|
if lease == nil {
|
||||||
|
toStore := false
|
||||||
|
for lease == nil {
|
||||||
|
lease = s.reserveLease(mac)
|
||||||
|
if lease == nil {
|
||||||
|
log.Debug("DHCPv4: No more IP addresses")
|
||||||
|
if toStore {
|
||||||
|
s.conf.notify(LeaseChangedDBStore)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
toStore = true
|
||||||
|
|
||||||
|
if !s.addrAvailable(lease.IP) {
|
||||||
|
s.blacklistLease(lease)
|
||||||
|
lease = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
s.conf.notify(LeaseChangedDBStore)
|
||||||
|
|
||||||
|
// s.conf.notify(LeaseChangedBlacklisted)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
reqIP := req.Options.Get(dhcpv4.OptionRequestedIPAddress)
|
||||||
|
if len(reqIP) != 0 &&
|
||||||
|
!bytes.Equal(reqIP, lease.IP) {
|
||||||
|
log.Debug("DHCPv4: different RequestedIP: %v != %v", reqIP, lease.IP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname := req.Options.Get(dhcpv4.OptionHostName)
|
||||||
|
lease.Hostname = string(hostname)
|
||||||
|
|
||||||
|
resp.UpdateOption(dhcpv4.OptMessageType(dhcpv4.MessageTypeOffer))
|
||||||
|
return lease
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process Request request and return lease
|
||||||
|
// Return false if we don't need to reply
|
||||||
|
func (s *V4Server) processRequest(req *dhcpv4.DHCPv4, resp *dhcpv4.DHCPv4) (*Lease, bool) {
|
||||||
|
var lease *Lease
|
||||||
|
mac := req.ClientHWAddr
|
||||||
|
hostname := req.Options.Get(dhcpv4.OptionHostName)
|
||||||
|
reqIP := req.Options.Get(dhcpv4.OptionRequestedIPAddress)
|
||||||
|
|
||||||
|
sid := req.Options.Get(dhcpv4.OptionServerIdentifier)
|
||||||
|
if len(sid) == 0 {
|
||||||
|
log.Debug("DHCPv4: No OptionServerIdentifier in Request message for %s", mac)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if !bytes.Equal(sid, s.conf.dnsIPAddrs[0]) {
|
||||||
|
log.Debug("DHCPv4: Bad OptionServerIdentifier in Request message for %s", mac)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(reqIP) != 4 {
|
||||||
|
log.Debug("DHCPv4: Bad OptionRequestedIPAddress in Request message for %s", mac)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
s.leasesLock.Lock()
|
||||||
|
for _, l := range s.leases {
|
||||||
|
if bytes.Equal(l.HWAddr, mac) {
|
||||||
|
if !bytes.Equal(l.IP, reqIP) {
|
||||||
|
s.leasesLock.Unlock()
|
||||||
|
log.Debug("DHCPv4: Mismatched OptionRequestedIPAddress in Request message for %s", mac)
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal([]byte(l.Hostname), hostname) {
|
||||||
|
s.leasesLock.Unlock()
|
||||||
|
log.Debug("DHCPv4: Mismatched OptionHostName in Request message for %s", mac)
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
|
||||||
|
lease = l
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.leasesLock.Unlock()
|
||||||
|
|
||||||
|
if lease == nil {
|
||||||
|
log.Debug("DHCPv4: No lease for %s", mac)
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
|
||||||
|
if lease.Expiry.Unix() != leaseExpireStatic {
|
||||||
|
|
||||||
|
lease.Expiry = time.Now().Add(s.conf.leaseTime)
|
||||||
|
|
||||||
|
s.leasesLock.Lock()
|
||||||
|
s.conf.notify(LeaseChangedDBStore)
|
||||||
|
s.leasesLock.Unlock()
|
||||||
|
|
||||||
|
s.conf.notify(LeaseChangedAdded)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.UpdateOption(dhcpv4.OptMessageType(dhcpv4.MessageTypeAck))
|
||||||
|
return lease, true
|
||||||
|
}
|
||||||
|
|
||||||
// Find a lease associated with MAC and prepare response
|
// Find a lease associated with MAC and prepare response
|
||||||
|
// Return 1: OK
|
||||||
|
// Return 0: error; reply with Nak
|
||||||
|
// Return -1: error; don't reply
|
||||||
func (s *V4Server) process(req *dhcpv4.DHCPv4, resp *dhcpv4.DHCPv4) int {
|
func (s *V4Server) process(req *dhcpv4.DHCPv4, resp *dhcpv4.DHCPv4) int {
|
||||||
|
|
||||||
var lease *Lease
|
var lease *Lease
|
||||||
mac := req.ClientHWAddr
|
|
||||||
if len(mac) != 6 {
|
|
||||||
log.Debug("DHCPv4: Invalid ClientHWAddr")
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
hostname := req.Options.Get(dhcpv4.OptionHostName)
|
|
||||||
reqIP := req.Options.Get(dhcpv4.OptionRequestedIPAddress)
|
|
||||||
|
|
||||||
resp.UpdateOption(dhcpv4.OptServerIdentifier(s.conf.dnsIPAddrs[0]))
|
resp.UpdateOption(dhcpv4.OptServerIdentifier(s.conf.dnsIPAddrs[0]))
|
||||||
|
|
||||||
switch req.MessageType() {
|
switch req.MessageType() {
|
||||||
|
|
||||||
case dhcpv4.MessageTypeDiscover:
|
case dhcpv4.MessageTypeDiscover:
|
||||||
|
lease = s.processDiscover(req, resp)
|
||||||
s.leasesLock.Lock()
|
|
||||||
defer s.leasesLock.Unlock()
|
|
||||||
|
|
||||||
lease = s.findLease(mac)
|
|
||||||
if lease == nil {
|
if lease == nil {
|
||||||
toStore := false
|
|
||||||
for lease == nil {
|
|
||||||
lease = s.reserveLease(mac)
|
|
||||||
if lease == nil {
|
|
||||||
log.Debug("DHCPv4: No more IP addresses")
|
|
||||||
if toStore {
|
|
||||||
s.conf.notify(LeaseChangedDBStore)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
toStore = true
|
|
||||||
|
|
||||||
if !s.addrAvailable(lease.IP) {
|
|
||||||
s.blacklistLease(lease)
|
|
||||||
lease = nil
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
s.conf.notify(LeaseChangedDBStore)
|
|
||||||
|
|
||||||
// s.conf.notify(LeaseChangedBlacklisted)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if len(reqIP) != 0 &&
|
|
||||||
!bytes.Equal(reqIP, lease.IP) {
|
|
||||||
log.Debug("DHCPv4: different RequestedIP: %v != %v", reqIP, lease.IP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lease.Hostname = string(hostname)
|
|
||||||
|
|
||||||
resp.UpdateOption(dhcpv4.OptMessageType(dhcpv4.MessageTypeOffer))
|
|
||||||
|
|
||||||
case dhcpv4.MessageTypeRequest:
|
|
||||||
|
|
||||||
sid := req.Options.Get(dhcpv4.OptionServerIdentifier)
|
|
||||||
if len(sid) == 0 {
|
|
||||||
log.Debug("DHCPv4: No OptionServerIdentifier in Request message for %s", mac)
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if !bytes.Equal(sid, s.conf.dnsIPAddrs[0]) {
|
|
||||||
log.Debug("DHCPv4: Bad OptionServerIdentifier in Request message for %s", mac)
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(reqIP) != 4 {
|
|
||||||
log.Debug("DHCPv4: Bad OptionRequestedIPAddress in Request message for %s", mac)
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
s.leasesLock.Lock()
|
|
||||||
for _, l := range s.leases {
|
|
||||||
if bytes.Equal(l.HWAddr, mac) {
|
|
||||||
if !bytes.Equal(l.IP, reqIP) {
|
|
||||||
s.leasesLock.Unlock()
|
|
||||||
log.Debug("DHCPv4: Mismatched OptionRequestedIPAddress in Request message for %s", mac)
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal([]byte(l.Hostname), hostname) {
|
|
||||||
s.leasesLock.Unlock()
|
|
||||||
log.Debug("DHCPv4: Mismatched OptionHostName in Request message for %s", mac)
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
lease = l
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.leasesLock.Unlock()
|
|
||||||
|
|
||||||
if lease == nil {
|
|
||||||
log.Debug("DHCPv4: No lease for %s", mac)
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if lease.Expiry.Unix() != leaseExpireStatic {
|
case dhcpv4.MessageTypeRequest:
|
||||||
|
var toReply bool
|
||||||
lease.Expiry = time.Now().Add(s.conf.leaseTime)
|
lease, toReply = s.processRequest(req, resp)
|
||||||
|
if lease == nil {
|
||||||
s.leasesLock.Lock()
|
if toReply {
|
||||||
s.conf.notify(LeaseChangedDBStore)
|
return 0
|
||||||
s.leasesLock.Unlock()
|
}
|
||||||
|
return -1 // drop packet
|
||||||
s.conf.notify(LeaseChangedAdded)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.UpdateOption(dhcpv4.OptMessageType(dhcpv4.MessageTypeAck))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.YourIPAddr = make([]byte, 4)
|
resp.YourIPAddr = make([]byte, 4)
|
||||||
|
@ -477,6 +508,11 @@ func (s *V4Server) packetHandler(conn net.PacketConn, peer net.Addr, req *dhcpv4
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(req.ClientHWAddr) != 6 {
|
||||||
|
log.Debug("DHCPv4: Invalid ClientHWAddr")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
r := s.process(req, resp)
|
r := s.process(req, resp)
|
||||||
if r < 0 {
|
if r < 0 {
|
||||||
return
|
return
|
||||||
|
@ -602,7 +638,7 @@ func v4Create(conf V4ServerConf) (*V4Server, error) {
|
||||||
if s.conf.ipEnd == nil {
|
if s.conf.ipEnd == nil {
|
||||||
return nil, fmt.Errorf("DHCPv4: %s", err)
|
return nil, fmt.Errorf("DHCPv4: %s", err)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(s.conf.ipStart[:3], s.conf.ipEnd[:3]) ||
|
if !net.IP.Equal(s.conf.ipStart[:3], s.conf.ipEnd[:3]) ||
|
||||||
s.conf.ipStart[3] > s.conf.ipEnd[3] {
|
s.conf.ipStart[3] > s.conf.ipEnd[3] {
|
||||||
return nil, fmt.Errorf("DHCPv4: range end IP should match range start IP")
|
return nil, fmt.Errorf("DHCPv4: range end IP should match range start IP")
|
||||||
}
|
}
|
||||||
|
|
15
dhcpd/v6.go
15
dhcpd/v6.go
|
@ -75,8 +75,13 @@ func (s *V6Server) GetLeases(flags int) []Lease {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindMACbyIP6 - find a MAC address by IP address in the currently active DHCP leases
|
// GetLeasesRef - get leases
|
||||||
func (s *V6Server) FindMACbyIP6(ip net.IP) net.HardwareAddr {
|
func (s *V6Server) GetLeasesRef() []*Lease {
|
||||||
|
return s.leases
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases
|
||||||
|
func (s *V6Server) FindMACbyIP(ip net.IP) net.HardwareAddr {
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
|
|
||||||
s.leasesLock.Lock()
|
s.leasesLock.Lock()
|
||||||
|
@ -126,7 +131,7 @@ func (s *V6Server) rmDynamicLease(lease Lease) error {
|
||||||
l = s.leases[i]
|
l = s.leases[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes.Equal(l.IP, lease.IP) {
|
if net.IP.Equal(l.IP, lease.IP) {
|
||||||
|
|
||||||
if l.Expiry.Unix() == leaseExpireStatic {
|
if l.Expiry.Unix() == leaseExpireStatic {
|
||||||
return fmt.Errorf("static lease already exists")
|
return fmt.Errorf("static lease already exists")
|
||||||
|
@ -191,10 +196,10 @@ func (s *V6Server) addLease(l *Lease) {
|
||||||
log.Debug("DHCPv6: added lease %s <-> %s", l.IP, l.HWAddr)
|
log.Debug("DHCPv6: added lease %s <-> %s", l.IP, l.HWAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a lease with the same properies
|
// Remove a lease with the same properties
|
||||||
func (s *V6Server) rmLease(lease Lease) error {
|
func (s *V6Server) rmLease(lease Lease) error {
|
||||||
for i, l := range s.leases {
|
for i, l := range s.leases {
|
||||||
if bytes.Equal(l.IP, lease.IP) {
|
if net.IP.Equal(l.IP, lease.IP) {
|
||||||
|
|
||||||
if !bytes.Equal(l.HWAddr, lease.HWAddr) ||
|
if !bytes.Equal(l.HWAddr, lease.HWAddr) ||
|
||||||
l.Hostname != lease.Hostname {
|
l.Hostname != lease.Hostname {
|
||||||
|
|
Loading…
Reference in a new issue