Pull request: 3225 bsd dhcp
Merge in DNS/adguard-home from 3225-bsd-dhcp to master Closes #3225. Closes #3417. Squashed commit of the following: commit e7ea691824c7ebc8cafd8c9e206679346cbc8592 Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Aug 12 17:02:02 2021 +0300 all: imp code, docs commit 5b598fc18a9b69a0256569f4c691bb6a2193dfbd Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Aug 12 16:28:12 2021 +0300 all: mv logic, imp code, docs, log changes commit e3e1577a668fe3e5c61d075c390e4bd7268181ba Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Aug 12 14:15:10 2021 +0300 dhcpd: imp checkother commit 3cc8b058195c30a7ef0b7741ee8463270d9e47ff Author: Eugene Burkov <e.burkov@adguard.com> Date: Wed Aug 11 13:20:18 2021 +0300 all: imp bsd support
This commit is contained in:
118
internal/aghnet/interfaces.go
Normal file
118
internal/aghnet/interfaces.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package aghnet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
)
|
||||
|
||||
// IPVersion is a documentational alias for int. Use it when the integer means
|
||||
// IP version.
|
||||
type IPVersion = int
|
||||
|
||||
// IP version constants.
|
||||
const (
|
||||
IPVersion4 IPVersion = 4
|
||||
IPVersion6 IPVersion = 6
|
||||
)
|
||||
|
||||
// NetIface is the interface for network interface methods.
|
||||
type NetIface interface {
|
||||
Addrs() ([]net.Addr, error)
|
||||
}
|
||||
|
||||
// IfaceIPAddrs returns the interface's IP addresses.
|
||||
func IfaceIPAddrs(iface NetIface, ipv IPVersion) (ips []net.IP, err error) {
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, a := range addrs {
|
||||
var ip net.IP
|
||||
switch a := a.(type) {
|
||||
case *net.IPAddr:
|
||||
ip = a.IP
|
||||
case *net.IPNet:
|
||||
ip = a.IP
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
// Assume that net.(*Interface).Addrs can only return valid IPv4
|
||||
// and IPv6 addresses. Thus, if it isn't an IPv4 address, it
|
||||
// must be an IPv6 one.
|
||||
switch ipv {
|
||||
case IPVersion4:
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
ips = append(ips, ip4)
|
||||
}
|
||||
case IPVersion6:
|
||||
if ip6 := ip.To4(); ip6 == nil {
|
||||
ips = append(ips, ip)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid ip version %d", ipv)
|
||||
}
|
||||
}
|
||||
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
// IfaceDNSIPAddrs returns IP addresses of the interface suitable to send to
|
||||
// clients as DNS addresses. If err is nil, addrs contains either no addresses
|
||||
// or at least two.
|
||||
//
|
||||
// It makes up to maxAttempts attempts to get the addresses if there are none,
|
||||
// each time using the provided backoff. Sometimes an interface needs a few
|
||||
// seconds to really ititialize.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/2304.
|
||||
func IfaceDNSIPAddrs(
|
||||
iface NetIface,
|
||||
ipv IPVersion,
|
||||
maxAttempts int,
|
||||
backoff time.Duration,
|
||||
) (addrs []net.IP, err error) {
|
||||
var n int
|
||||
for n = 1; n <= maxAttempts; n++ {
|
||||
addrs, err = IfaceIPAddrs(iface, ipv)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting ip addrs: %w", err)
|
||||
}
|
||||
|
||||
if len(addrs) > 0 {
|
||||
break
|
||||
}
|
||||
|
||||
log.Debug("dhcpv%d: attempt %d: no ip addresses", ipv, n)
|
||||
|
||||
time.Sleep(backoff)
|
||||
}
|
||||
|
||||
switch len(addrs) {
|
||||
case 0:
|
||||
// Don't return errors in case the users want to try and enable
|
||||
// the DHCP server later.
|
||||
t := time.Duration(n) * backoff
|
||||
log.Error("dhcpv%d: no ip for iface after %d attempts and %s", ipv, n, t)
|
||||
|
||||
return nil, nil
|
||||
case 1:
|
||||
// Some Android devices use 8.8.8.8 if there is not a secondary
|
||||
// DNS server. Fix that by setting the secondary DNS address to
|
||||
// the same address.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/1708.
|
||||
log.Debug("dhcpv%d: setting secondary dns ip to itself", ipv)
|
||||
addrs = append(addrs, addrs[0])
|
||||
default:
|
||||
// Go on.
|
||||
}
|
||||
|
||||
log.Debug("dhcpv%d: got addresses %s after %d attempts", ipv, addrs, n)
|
||||
|
||||
return addrs, nil
|
||||
}
|
||||
Reference in New Issue
Block a user