Pull request: 2508 ip conversion vol.1

Merge in DNS/adguard-home from 2508-ip-conversion to master

Updates #2508.

Squashed commit of the following:

commit 3f64709fbc73ef74c11b910997be1e9bc337193c
Merge: 5ac7faaaa 0d67aa251
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Wed Jan 13 16:21:34 2021 +0300

    Merge branch 'master' into 2508-ip-conversion

commit 5ac7faaaa9dda570fdb872acad5d13d078f46b64
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Wed Jan 13 12:00:11 2021 +0300

    all: replace conditions with appropriate functions in tests

commit 9e3fa9a115ed23024c57dd5192d5173477ddbf71
Merge: db992a42a bba74859e
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Wed Jan 13 10:47:10 2021 +0300

    Merge branch 'master' into 2508-ip-conversion

commit db992a42a2c6f315421e78a6a0492e2bfb3ce89d
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Jan 12 18:55:53 2021 +0300

    sysutil: fix linux tests

commit f629b15d62349323ce2da05e68dc9cc0b5f6e194
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Jan 12 18:41:20 2021 +0300

    all: improve code quality

commit 3bf03a75524040738562298bd1de6db536af130f
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Jan 12 17:33:26 2021 +0300

    sysutil: fix linux net.IP conversion

commit 5d5b6994916923636e635588631b63b7e7b74e5f
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Jan 12 14:57:26 2021 +0300

    dnsforward: remove redundant net.IP <-> string conversion

commit 0b955d99b7fad40942f21d1dd8734adb99126195
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Jan 11 18:04:25 2021 +0300

    dhcpd: remove net.IP <-> string conversion
This commit is contained in:
Eugene Burkov
2021-01-13 16:56:05 +03:00
parent 0d67aa251d
commit e8c1f5c8d3
39 changed files with 409 additions and 435 deletions

View File

@@ -8,28 +8,28 @@ import (
func TestIsBlockedIPAllowed(t *testing.T) {
a := &accessCtx{}
assert.True(t, a.Init([]string{"1.1.1.1", "2.2.0.0/16"}, nil, nil) == nil)
assert.Nil(t, a.Init([]string{"1.1.1.1", "2.2.0.0/16"}, nil, nil))
disallowed, disallowedRule := a.IsBlockedIP("1.1.1.1")
assert.False(t, disallowed)
assert.Equal(t, "", disallowedRule)
assert.Empty(t, disallowedRule)
disallowed, disallowedRule = a.IsBlockedIP("1.1.1.2")
assert.True(t, disallowed)
assert.Equal(t, "", disallowedRule)
assert.Empty(t, disallowedRule)
disallowed, disallowedRule = a.IsBlockedIP("2.2.1.1")
assert.False(t, disallowed)
assert.Equal(t, "", disallowedRule)
assert.Empty(t, disallowedRule)
disallowed, disallowedRule = a.IsBlockedIP("2.3.1.1")
assert.True(t, disallowed)
assert.Equal(t, "", disallowedRule)
assert.Empty(t, disallowedRule)
}
func TestIsBlockedIPDisallowed(t *testing.T) {
a := &accessCtx{}
assert.True(t, a.Init(nil, []string{"1.1.1.1", "2.2.0.0/16"}, nil) == nil)
assert.Nil(t, a.Init(nil, []string{"1.1.1.1", "2.2.0.0/16"}, nil))
disallowed, disallowedRule := a.IsBlockedIP("1.1.1.1")
assert.True(t, disallowed)
@@ -37,7 +37,7 @@ func TestIsBlockedIPDisallowed(t *testing.T) {
disallowed, disallowedRule = a.IsBlockedIP("1.1.1.2")
assert.False(t, disallowed)
assert.Equal(t, "", disallowedRule)
assert.Empty(t, disallowedRule)
disallowed, disallowedRule = a.IsBlockedIP("2.2.1.1")
assert.True(t, disallowed)
@@ -45,7 +45,7 @@ func TestIsBlockedIPDisallowed(t *testing.T) {
disallowed, disallowedRule = a.IsBlockedIP("2.3.1.1")
assert.False(t, disallowed)
assert.Equal(t, "", disallowedRule)
assert.Empty(t, disallowedRule)
}
func TestIsBlockedIPBlockedDomain(t *testing.T) {
@@ -60,13 +60,13 @@ func TestIsBlockedIPBlockedDomain(t *testing.T) {
// match by "host2.com"
assert.True(t, a.IsBlockedDomain("host1"))
assert.True(t, a.IsBlockedDomain("host2"))
assert.True(t, !a.IsBlockedDomain("host3"))
assert.False(t, a.IsBlockedDomain("host3"))
// match by wildcard "*.host.com"
assert.True(t, !a.IsBlockedDomain("host.com"))
assert.False(t, a.IsBlockedDomain("host.com"))
assert.True(t, a.IsBlockedDomain("asdf.host.com"))
assert.True(t, a.IsBlockedDomain("qwer.asdf.host.com"))
assert.True(t, !a.IsBlockedDomain("asdf.zhost.com"))
assert.False(t, a.IsBlockedDomain("asdf.zhost.com"))
// match by wildcard "||host3.com^"
assert.True(t, a.IsBlockedDomain("host3.com"))

View File

@@ -29,17 +29,16 @@ type FilteringConfig struct {
// GetCustomUpstreamByClient - a callback function that returns upstreams configuration
// based on the client IP address. Returns nil if there are no custom upstreams for the client
// TODO(e.burkov): replace argument type with net.IP.
GetCustomUpstreamByClient func(clientAddr string) *proxy.UpstreamConfig `yaml:"-"`
// Protection configuration
// --
ProtectionEnabled bool `yaml:"protection_enabled"` // whether or not use any of dnsfilter features
BlockingMode string `yaml:"blocking_mode"` // mode how to answer filtered requests
BlockingIPv4 string `yaml:"blocking_ipv4"` // IP address to be returned for a blocked A request
BlockingIPv6 string `yaml:"blocking_ipv6"` // IP address to be returned for a blocked AAAA request
BlockingIPAddrv4 net.IP `yaml:"-"`
BlockingIPAddrv6 net.IP `yaml:"-"`
ProtectionEnabled bool `yaml:"protection_enabled"` // whether or not use any of dnsfilter features
BlockingMode string `yaml:"blocking_mode"` // mode how to answer filtered requests
BlockingIPv4 net.IP `yaml:"blocking_ipv4"` // IP address to be returned for a blocked A request
BlockingIPv6 net.IP `yaml:"blocking_ipv6"` // IP address to be returned for a blocked AAAA request
BlockedResponseTTL uint32 `yaml:"blocked_response_ttl"` // if 0, then default is used (3600)
// IP (or domain name) which is used to respond to DNS requests blocked by parental control or safe-browsing

View File

@@ -182,7 +182,7 @@ func processInternalHosts(ctx *dnsContext) int {
return resultDone
}
log.Debug("DNS: internal record: %s -> %s", req.Question[0].Name, ip.String())
log.Debug("DNS: internal record: %s -> %s", req.Question[0].Name, ip)
resp := s.makeResponse(req)
@@ -278,7 +278,7 @@ func processFilteringBeforeRequest(ctx *dnsContext) int {
return resultDone
}
// Pass request to upstream servers; process the response
// processUpstream passes request to upstream servers and handles the response.
func processUpstream(ctx *dnsContext) int {
s := ctx.srv
d := ctx.proxyCtx
@@ -287,7 +287,7 @@ func processUpstream(ctx *dnsContext) int {
}
if d.Addr != nil && s.conf.GetCustomUpstreamByClient != nil {
clientIP := ipFromAddr(d.Addr)
clientIP := IPStringFromAddr(d.Addr)
upstreamsConf := s.conf.GetCustomUpstreamByClient(clientIP)
if upstreamsConf != nil {
log.Debug("Using custom upstreams for %s", clientIP)

View File

@@ -178,9 +178,7 @@ func (s *Server) Prepare(config *ServerConfig) error {
if config != nil {
s.conf = *config
if s.conf.BlockingMode == "custom_ip" {
s.conf.BlockingIPAddrv4 = net.ParseIP(s.conf.BlockingIPv4)
s.conf.BlockingIPAddrv6 = net.ParseIP(s.conf.BlockingIPv6)
if s.conf.BlockingIPAddrv4 == nil || s.conf.BlockingIPAddrv6 == nil {
if s.conf.BlockingIPv4 == nil || s.conf.BlockingIPv6 == nil {
return fmt.Errorf("dns: invalid custom blocking IP address specified")
}
}

View File

@@ -286,7 +286,7 @@ func TestBlockedRequest(t *testing.T) {
t.Fatalf("Couldn't talk to server %s: %s", addr, err)
}
assert.Equal(t, dns.RcodeSuccess, reply.Rcode)
assert.True(t, reply.Answer[0].(*dns.A).A.Equal(net.ParseIP("0.0.0.0")))
assert.True(t, reply.Answer[0].(*dns.A).A.Equal(net.IP{0, 0, 0, 0}))
err = s.Stop()
if err != nil {
@@ -300,7 +300,7 @@ func TestServerCustomClientUpstream(t *testing.T) {
uc := &proxy.UpstreamConfig{}
u := &testUpstream{}
u.ipv4 = map[string][]net.IP{}
u.ipv4["host."] = []net.IP{net.ParseIP("192.168.0.1")}
u.ipv4["host."] = []net.IP{{192, 168, 0, 1}}
uc.Upstreams = append(uc.Upstreams, u)
return uc
}
@@ -425,7 +425,7 @@ func TestBlockCNAMEProtectionEnabled(t *testing.T) {
testUpstm := &testUpstream{testCNAMEs, testIPv4, nil}
s.conf.ProtectionEnabled = false
err := s.startWithUpstream(testUpstm)
assert.True(t, err == nil)
assert.Nil(t, err)
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
// 'badhost' has a canonical name 'null.example.org' which is blocked by filters:
@@ -440,16 +440,16 @@ func TestBlockCNAME(t *testing.T) {
s := createTestServer(t)
testUpstm := &testUpstream{testCNAMEs, testIPv4, nil}
err := s.startWithUpstream(testUpstm)
assert.True(t, err == nil)
assert.Nil(t, err)
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
// 'badhost' has a canonical name 'null.example.org' which is blocked by filters:
// response is blocked
req := createTestMessage("badhost.")
reply, err := dns.Exchange(req, addr.String())
assert.Nil(t, err, nil)
assert.Nil(t, err)
assert.Equal(t, dns.RcodeSuccess, reply.Rcode)
assert.True(t, reply.Answer[0].(*dns.A).A.Equal(net.ParseIP("0.0.0.0")))
assert.True(t, reply.Answer[0].(*dns.A).A.Equal(net.IP{0, 0, 0, 0}))
// 'whitelist.example.org' has a canonical name 'null.example.org' which is blocked by filters
// but 'whitelist.example.org' is in a whitelist:
@@ -465,7 +465,7 @@ func TestBlockCNAME(t *testing.T) {
reply, err = dns.Exchange(req, addr.String())
assert.Nil(t, err)
assert.Equal(t, dns.RcodeSuccess, reply.Rcode)
assert.True(t, reply.Answer[0].(*dns.A).A.Equal(net.ParseIP("0.0.0.0")))
assert.True(t, reply.Answer[0].(*dns.A).A.Equal(net.IP{0, 0, 0, 0}))
_ = s.Stop()
}
@@ -548,13 +548,13 @@ func TestBlockedCustomIP(t *testing.T) {
conf.TCPListenAddr = &net.TCPAddr{Port: 0}
conf.ProtectionEnabled = true
conf.BlockingMode = "custom_ip"
conf.BlockingIPv4 = "bad IP"
conf.BlockingIPv4 = nil
conf.UpstreamDNS = []string{"8.8.8.8:53", "8.8.4.4:53"}
err := s.Prepare(&conf)
assert.True(t, err != nil) // invalid BlockingIPv4
assert.NotNil(t, err) // invalid BlockingIPv4
conf.BlockingIPv4 = "0.0.0.1"
conf.BlockingIPv6 = "::1"
conf.BlockingIPv4 = net.IP{0, 0, 0, 1}
conf.BlockingIPv6 = net.ParseIP("::1")
err = s.Prepare(&conf)
assert.Nil(t, err)
err = s.Start()
@@ -565,7 +565,7 @@ func TestBlockedCustomIP(t *testing.T) {
req := createTestMessageWithType("null.example.org.", dns.TypeA)
reply, err := dns.Exchange(req, addr.String())
assert.Nil(t, err)
assert.Equal(t, 1, len(reply.Answer))
assert.Len(t, reply.Answer, 1)
a, ok := reply.Answer[0].(*dns.A)
assert.True(t, ok)
assert.Equal(t, "0.0.0.1", a.A.String())
@@ -573,7 +573,7 @@ func TestBlockedCustomIP(t *testing.T) {
req = createTestMessageWithType("null.example.org.", dns.TypeAAAA)
reply, err = dns.Exchange(req, addr.String())
assert.Nil(t, err)
assert.Equal(t, 1, len(reply.Answer))
assert.Len(t, reply.Answer, 1)
a6, ok := reply.Answer[0].(*dns.AAAA)
assert.True(t, ok)
assert.Equal(t, "::1", a6.AAAA.String())
@@ -710,7 +710,7 @@ func TestRewrite(t *testing.T) {
req := createTestMessageWithType("test.com.", dns.TypeA)
reply, err := dns.Exchange(req, addr.String())
assert.Nil(t, err)
assert.Equal(t, 1, len(reply.Answer))
assert.Len(t, reply.Answer, 1)
a, ok := reply.Answer[0].(*dns.A)
assert.True(t, ok)
assert.Equal(t, "1.2.3.4", a.A.String())
@@ -718,12 +718,12 @@ func TestRewrite(t *testing.T) {
req = createTestMessageWithType("test.com.", dns.TypeAAAA)
reply, err = dns.Exchange(req, addr.String())
assert.Nil(t, err)
assert.Equal(t, 0, len(reply.Answer))
assert.Empty(t, reply.Answer)
req = createTestMessageWithType("alias.test.com.", dns.TypeA)
reply, err = dns.Exchange(req, addr.String())
assert.Nil(t, err)
assert.Equal(t, 2, len(reply.Answer))
assert.Len(t, reply.Answer, 2)
assert.Equal(t, "test.com.", reply.Answer[0].(*dns.CNAME).Target)
assert.Equal(t, "1.2.3.4", reply.Answer[1].(*dns.A).A.String())
@@ -731,7 +731,7 @@ func TestRewrite(t *testing.T) {
reply, err = dns.Exchange(req, addr.String())
assert.Nil(t, err)
assert.Equal(t, "my.alias.example.org.", reply.Question[0].Name) // the original question is restored
assert.Equal(t, 2, len(reply.Answer))
assert.Len(t, reply.Answer, 2)
assert.Equal(t, "example.org.", reply.Answer[0].(*dns.CNAME).Target)
assert.Equal(t, dns.TypeA, reply.Answer[1].Header().Rrtype)
@@ -765,7 +765,7 @@ func createTestServer(t *testing.T) *Server {
s.conf.ConfigModified = func() {}
err := s.Prepare(nil)
assert.True(t, err == nil)
assert.Nil(t, err)
return s
}
@@ -1011,16 +1011,14 @@ func TestValidateUpstreamsSet(t *testing.T) {
assert.NotNil(t, err, "there is an invalid upstream in set, but it pass through validation")
}
func TestIpFromAddr(t *testing.T) {
func TestIPStringFromAddr(t *testing.T) {
addr := net.UDPAddr{}
addr.IP = net.ParseIP("1:2:3::4")
addr.Port = 12345
addr.Zone = "eth0"
a := ipFromAddr(&addr)
assert.True(t, a == "1:2:3::4")
assert.Equal(t, IPStringFromAddr(&addr), net.ParseIP("1:2:3::4").String())
a = ipFromAddr(nil)
assert.True(t, a == "")
assert.Empty(t, IPStringFromAddr(nil))
}
func TestMatchDNSName(t *testing.T) {
@@ -1030,9 +1028,9 @@ func TestMatchDNSName(t *testing.T) {
assert.True(t, matchDNSName(dnsNames, "a.host2"))
assert.True(t, matchDNSName(dnsNames, "b.a.host2"))
assert.True(t, matchDNSName(dnsNames, "1.2.3.4"))
assert.True(t, !matchDNSName(dnsNames, "host2"))
assert.True(t, !matchDNSName(dnsNames, ""))
assert.True(t, !matchDNSName(dnsNames, "*.host2"))
assert.False(t, matchDNSName(dnsNames, "host2"))
assert.False(t, matchDNSName(dnsNames, ""))
assert.False(t, matchDNSName(dnsNames, "*.host2"))
}
type testDHCP struct {
@@ -1040,7 +1038,7 @@ type testDHCP struct {
func (d *testDHCP) Leases(flags int) []dhcpd.Lease {
l := dhcpd.Lease{}
l.IP = net.ParseIP("127.0.0.1").To4()
l.IP = net.IP{127, 0, 0, 1}
l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa")
l.Hostname = "localhost"
return []dhcpd.Lease{l}
@@ -1058,7 +1056,7 @@ func TestPTRResponseFromDHCPLeases(t *testing.T) {
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
s.conf.FilteringConfig.ProtectionEnabled = true
err := s.Prepare(nil)
assert.True(t, err == nil)
assert.Nil(t, err)
assert.Nil(t, s.Start())
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
@@ -1067,7 +1065,7 @@ func TestPTRResponseFromDHCPLeases(t *testing.T) {
resp, err := dns.Exchange(req, addr.String())
assert.Nil(t, err)
assert.Equal(t, 1, len(resp.Answer))
assert.Len(t, resp.Answer, 1)
assert.Equal(t, dns.TypePTR, resp.Answer[0].Header().Rrtype)
assert.Equal(t, "1.0.0.127.in-addr.arpa.", resp.Answer[0].Header().Name)
ptr := resp.Answer[0].(*dns.PTR)
@@ -1100,7 +1098,7 @@ func TestPTRResponseFromHosts(t *testing.T) {
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
s.conf.FilteringConfig.ProtectionEnabled = true
err := s.Prepare(nil)
assert.True(t, err == nil)
assert.Nil(t, err)
assert.Nil(t, s.Start())
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
@@ -1109,7 +1107,7 @@ func TestPTRResponseFromHosts(t *testing.T) {
resp, err := dns.Exchange(req, addr.String())
assert.Nil(t, err)
assert.Equal(t, 1, len(resp.Answer))
assert.Len(t, resp.Answer, 1)
assert.Equal(t, dns.TypePTR, resp.Answer[0].Header().Rrtype)
assert.Equal(t, "1.0.0.127.in-addr.arpa.", resp.Answer[0].Header().Name)
ptr := resp.Answer[0].(*dns.PTR)

View File

@@ -12,7 +12,7 @@ import (
)
func (s *Server) beforeRequestHandler(_ *proxy.Proxy, d *proxy.DNSContext) (bool, error) {
ip := ipFromAddr(d.Addr)
ip := IPStringFromAddr(d.Addr)
disallowed, _ := s.access.IsBlockedIP(ip)
if disallowed {
log.Tracef("Client IP %s is blocked by settings", ip)
@@ -36,7 +36,7 @@ func (s *Server) getClientRequestFilteringSettings(d *proxy.DNSContext) *dnsfilt
setts := s.dnsFilter.GetConfig()
setts.FilteringEnabled = true
if s.conf.FilterHandler != nil {
clientAddr := ipFromAddr(d.Addr)
clientAddr := IPStringFromAddr(d.Addr)
s.conf.FilterHandler(clientAddr, &setts)
}
return &setts

View File

@@ -28,8 +28,8 @@ type dnsConfig struct {
ProtectionEnabled *bool `json:"protection_enabled"`
RateLimit *uint32 `json:"ratelimit"`
BlockingMode *string `json:"blocking_mode"`
BlockingIPv4 *string `json:"blocking_ipv4"`
BlockingIPv6 *string `json:"blocking_ipv6"`
BlockingIPv4 net.IP `json:"blocking_ipv4"`
BlockingIPv6 net.IP `json:"blocking_ipv6"`
EDNSCSEnabled *bool `json:"edns_cs_enabled"`
DNSSECEnabled *bool `json:"dnssec_enabled"`
DisableIPv6 *bool `json:"disable_ipv6"`
@@ -68,8 +68,8 @@ func (s *Server) getDNSConfig() dnsConfig {
Bootstraps: &bootstraps,
ProtectionEnabled: &protectionEnabled,
BlockingMode: &blockingMode,
BlockingIPv4: &BlockingIPv4,
BlockingIPv6: &BlockingIPv6,
BlockingIPv4: BlockingIPv4,
BlockingIPv6: BlockingIPv6,
RateLimit: &Ratelimit,
EDNSCSEnabled: &EnableEDNSClientSubnet,
DNSSECEnabled: &EnableDNSSEC,
@@ -100,17 +100,11 @@ func (req *dnsConfig) checkBlockingMode() bool {
bm := *req.BlockingMode
if bm == "custom_ip" {
if req.BlockingIPv4 == nil || req.BlockingIPv6 == nil {
if req.BlockingIPv4.To4() == nil {
return false
}
ip4 := net.ParseIP(*req.BlockingIPv4)
if ip4 == nil || ip4.To4() == nil {
return false
}
ip6 := net.ParseIP(*req.BlockingIPv6)
return ip6 != nil
return req.BlockingIPv6 != nil
}
for _, valid := range []string{
@@ -247,10 +241,8 @@ func (s *Server) setConfig(dc dnsConfig) (restart bool) {
if dc.BlockingMode != nil {
s.conf.BlockingMode = *dc.BlockingMode
if *dc.BlockingMode == "custom_ip" {
s.conf.BlockingIPv4 = *dc.BlockingIPv4
s.conf.BlockingIPAddrv4 = net.ParseIP(*dc.BlockingIPv4)
s.conf.BlockingIPv6 = *dc.BlockingIPv6
s.conf.BlockingIPAddrv6 = net.ParseIP(*dc.BlockingIPv6)
s.conf.BlockingIPv4 = dc.BlockingIPv4.To4()
s.conf.BlockingIPv6 = dc.BlockingIPv6.To16()
}
}

View File

@@ -60,9 +60,9 @@ func (s *Server) genDNSFilterMessage(d *proxy.DNSContext, result *dnsfilter.Resu
switch m.Question[0].Qtype {
case dns.TypeA:
return s.genARecord(m, s.conf.BlockingIPAddrv4)
return s.genARecord(m, s.conf.BlockingIPv4)
case dns.TypeAAAA:
return s.genAAAARecord(m, s.conf.BlockingIPAddrv6)
return s.genAAAARecord(m, s.conf.BlockingIPv6)
}
} else if s.conf.BlockingMode == "nxdomain" {
// means that we should return NXDOMAIN for any blocked request

View File

@@ -36,7 +36,7 @@ func processQueryLogsAndStats(ctx *dnsContext) int {
OrigAnswer: ctx.origResp,
Result: ctx.result,
Elapsed: elapsed,
ClientIP: getIP(d.Addr),
ClientIP: ipFromAddr(d.Addr),
}
switch d.Proto {

View File

@@ -8,38 +8,8 @@ import (
"github.com/AdguardTeam/golibs/utils"
)
// GetIPString is a helper function that extracts IP address from net.Addr
func GetIPString(addr net.Addr) string {
switch addr := addr.(type) {
case *net.UDPAddr:
return addr.IP.String()
case *net.TCPAddr:
return addr.IP.String()
}
return ""
}
func stringArrayDup(a []string) []string {
a2 := make([]string, len(a))
copy(a2, a)
return a2
}
// Get IP address from net.Addr object
// Note: we can't use net.SplitHostPort(a.String()) because of IPv6 zone:
// https://github.com/AdguardTeam/AdGuardHome/internal/issues/1261
func ipFromAddr(a net.Addr) string {
switch addr := a.(type) {
case *net.UDPAddr:
return addr.IP.String()
case *net.TCPAddr:
return addr.IP.String()
}
return ""
}
// Get IP address from net.Addr
func getIP(addr net.Addr) net.IP {
// ipFromAddr gets IP address from addr.
func ipFromAddr(addr net.Addr) (ip net.IP) {
switch addr := addr.(type) {
case *net.UDPAddr:
return addr.IP
@@ -49,6 +19,23 @@ func getIP(addr net.Addr) net.IP {
return nil
}
// IPStringFromAddr extracts IP address from net.Addr.
// Note: we can't use net.SplitHostPort(a.String()) because of IPv6 zone:
// https://github.com/AdguardTeam/AdGuardHome/internal/issues/1261
func IPStringFromAddr(addr net.Addr) (ipstr string) {
if ip := ipFromAddr(addr); ip != nil {
return ip.String()
}
return ""
}
func stringArrayDup(a []string) []string {
a2 := make([]string, len(a))
copy(a2, a)
return a2
}
// Find value in a sorted array
func findSorted(ar []string, val string) int {
i := sort.SearchStrings(ar, val)