mirror of
				https://github.com/AdguardTeam/AdGuardHome.git
				synced 2022-10-30 02:30:37 +03:00 
			
		
		
		
	 00a61fdea0
			
		
	
	00a61fdea0
	
	
	
		
			
			Merge in DNS/adguard-home from use-renameio to master Squashed commit of the following: commit 807cda37b0e9e49539c1a8ce7912b74bd3c05b08 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Apr 6 19:54:21 2021 +0300 all: use renameio instead of golibs/file
		
			
				
	
	
		
			177 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // On-disk database for lease table
 | |
| 
 | |
| package dhcpd
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"errors"
 | |
| 	"io/ioutil"
 | |
| 	"net"
 | |
| 	"os"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/AdguardTeam/golibs/log"
 | |
| 	"github.com/google/renameio/maybe"
 | |
| )
 | |
| 
 | |
| const dbFilename = "leases.db"
 | |
| 
 | |
| type leaseJSON struct {
 | |
| 	HWAddr   []byte `json:"mac"`
 | |
| 	IP       []byte `json:"ip"`
 | |
| 	Hostname string `json:"host"`
 | |
| 	Expiry   int64  `json:"exp"`
 | |
| }
 | |
| 
 | |
| func normalizeIP(ip net.IP) net.IP {
 | |
| 	ip4 := ip.To4()
 | |
| 	if ip4 != nil {
 | |
| 		return ip4
 | |
| 	}
 | |
| 	return ip
 | |
| }
 | |
| 
 | |
| // Load lease table from DB
 | |
| func (s *Server) dbLoad() {
 | |
| 	dynLeases := []*Lease{}
 | |
| 	staticLeases := []*Lease{}
 | |
| 	v6StaticLeases := []*Lease{}
 | |
| 	v6DynLeases := []*Lease{}
 | |
| 
 | |
| 	data, err := ioutil.ReadFile(s.conf.DBFilePath)
 | |
| 	if err != nil {
 | |
| 		if !errors.Is(err, os.ErrNotExist) {
 | |
| 			log.Error("dhcp: can't read file %q: %v", s.conf.DBFilePath, err)
 | |
| 		}
 | |
| 
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	obj := []leaseJSON{}
 | |
| 	err = json.Unmarshal(data, &obj)
 | |
| 	if err != nil {
 | |
| 		log.Error("dhcp: invalid DB: %v", err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	numLeases := len(obj)
 | |
| 	for i := range obj {
 | |
| 		obj[i].IP = normalizeIP(obj[i].IP)
 | |
| 
 | |
| 		if !(len(obj[i].IP) == 4 || len(obj[i].IP) == 16) {
 | |
| 			log.Info("dhcp: invalid IP: %s", obj[i].IP)
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		lease := Lease{
 | |
| 			HWAddr:   obj[i].HWAddr,
 | |
| 			IP:       obj[i].IP,
 | |
| 			Hostname: obj[i].Hostname,
 | |
| 			Expiry:   time.Unix(obj[i].Expiry, 0),
 | |
| 		}
 | |
| 
 | |
| 		if len(obj[i].IP) == 16 {
 | |
| 			if obj[i].Expiry == leaseExpireStatic {
 | |
| 				v6StaticLeases = append(v6StaticLeases, &lease)
 | |
| 			} else {
 | |
| 				v6DynLeases = append(v6DynLeases, &lease)
 | |
| 			}
 | |
| 		} else {
 | |
| 			if obj[i].Expiry == leaseExpireStatic {
 | |
| 				staticLeases = append(staticLeases, &lease)
 | |
| 			} else {
 | |
| 				dynLeases = append(dynLeases, &lease)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	leases4 := normalizeLeases(staticLeases, dynLeases)
 | |
| 	s.srv4.ResetLeases(leases4)
 | |
| 
 | |
| 	leases6 := normalizeLeases(v6StaticLeases, v6DynLeases)
 | |
| 	if s.srv6 != nil {
 | |
| 		s.srv6.ResetLeases(leases6)
 | |
| 	}
 | |
| 
 | |
| 	log.Info("dhcp: loaded leases v4:%d  v6:%d  total-read:%d from DB",
 | |
| 		len(leases4), len(leases6), numLeases)
 | |
| }
 | |
| 
 | |
| // Skip duplicate leases
 | |
| // Static leases have a priority over dynamic leases
 | |
| func normalizeLeases(staticLeases, dynLeases []*Lease) []*Lease {
 | |
| 	leases := []*Lease{}
 | |
| 	index := map[string]int{}
 | |
| 
 | |
| 	for i, lease := range staticLeases {
 | |
| 		_, ok := index[lease.HWAddr.String()]
 | |
| 		if ok {
 | |
| 			continue // skip the lease with the same HW address
 | |
| 		}
 | |
| 		index[lease.HWAddr.String()] = i
 | |
| 		leases = append(leases, lease)
 | |
| 	}
 | |
| 
 | |
| 	for i, lease := range dynLeases {
 | |
| 		_, ok := index[lease.HWAddr.String()]
 | |
| 		if ok {
 | |
| 			continue // skip the lease with the same HW address
 | |
| 		}
 | |
| 		index[lease.HWAddr.String()] = i
 | |
| 		leases = append(leases, lease)
 | |
| 	}
 | |
| 
 | |
| 	return leases
 | |
| }
 | |
| 
 | |
| // Store lease table in DB
 | |
| func (s *Server) dbStore() {
 | |
| 	var leases []leaseJSON
 | |
| 
 | |
| 	leases4 := s.srv4.getLeasesRef()
 | |
| 	for _, l := range leases4 {
 | |
| 		if l.Expiry.Unix() == 0 {
 | |
| 			continue
 | |
| 		}
 | |
| 		lease := leaseJSON{
 | |
| 			HWAddr:   l.HWAddr,
 | |
| 			IP:       l.IP,
 | |
| 			Hostname: l.Hostname,
 | |
| 			Expiry:   l.Expiry.Unix(),
 | |
| 		}
 | |
| 		leases = append(leases, lease)
 | |
| 	}
 | |
| 
 | |
| 	if s.srv6 != nil {
 | |
| 		leases6 := s.srv6.getLeasesRef()
 | |
| 		for _, l := range leases6 {
 | |
| 			if l.Expiry.Unix() == 0 {
 | |
| 				continue
 | |
| 			}
 | |
| 			lease := leaseJSON{
 | |
| 				HWAddr:   l.HWAddr,
 | |
| 				IP:       l.IP,
 | |
| 				Hostname: l.Hostname,
 | |
| 				Expiry:   l.Expiry.Unix(),
 | |
| 			}
 | |
| 			leases = append(leases, lease)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	data, err := json.Marshal(leases)
 | |
| 	if err != nil {
 | |
| 		log.Error("json.Marshal: %v", err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = maybe.WriteFile(s.conf.DBFilePath, data, 0o644)
 | |
| 	if err != nil {
 | |
| 		log.Error("dhcp: can't store lease table on disk: %v  filename: %s",
 | |
| 			err, s.conf.DBFilePath)
 | |
| 
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	log.Info("dhcp: stored %d leases in DB", len(leases))
 | |
| }
 |