Skip to content

Commit

Permalink
Pull request: imp code: net.IP to netip.Addr
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit bb2a117
Merge: 085d057 f661fdc
Author: Dimitry Kolyshev <[email protected]>
Date:   Thu Nov 30 11:33:51 2023 +0200

    Merge remote-tracking branch 'origin/master' into imp-netip-addr

commit 085d057
Author: Dimitry Kolyshev <[email protected]>
Date:   Thu Nov 30 10:57:25 2023 +0200

    proxy: imp code

commit b1d6bad
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Nov 29 11:38:37 2023 +0200

    proxy: imp code

commit d7abf22
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Nov 29 11:37:35 2023 +0200

    main: imp code

commit fe46115
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Nov 29 11:36:20 2023 +0200

    proxy: imp code

commit f4c3f14
Merge: 8c0b793 6bdb8e9
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Nov 29 11:28:22 2023 +0200

    Merge remote-tracking branch 'origin/imp-netip-addr' into imp-netip-addr

    # Conflicts:
    #	upstream/parallel_test.go

commit 8c0b793
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Nov 29 11:27:01 2023 +0200

    fastip: imp code

commit f1541d9
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Nov 29 11:02:21 2023 +0200

    upstream: imp code

commit 6bdb8e9
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Nov 29 11:02:21 2023 +0200

    upstream: imp code

commit 1660146
Author: Dimitry Kolyshev <[email protected]>
Date:   Tue Nov 28 15:43:24 2023 +0200

    all: netutil imp code

commit 70ea807
Author: Dimitry Kolyshev <[email protected]>
Date:   Tue Nov 28 12:20:35 2023 +0200

    main: imp code

commit 7927130
Author: Dimitry Kolyshev <[email protected]>
Date:   Tue Nov 28 13:35:31 2023 +0200

    all: imp code

commit 5a09ecd
Author: Dimitry Kolyshev <[email protected]>
Date:   Tue Nov 28 13:18:14 2023 +0200

    all: imp code
  • Loading branch information
Mizzick committed Dec 1, 2023
1 parent f661fdc commit 5eb940d
Show file tree
Hide file tree
Showing 14 changed files with 221 additions and 223 deletions.
67 changes: 38 additions & 29 deletions fastip/fastest_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package fastip

import (
"net"
"net/netip"
"testing"

Expand All @@ -21,7 +20,7 @@ func TestFastestAddr_ExchangeFastest(t *testing.T) {
}
f := NewFastestAddr()

resp, up, err := f.ExchangeFastest(testARequest(t), []upstream.Upstream{u})
resp, up, err := f.ExchangeFastest(newTestReq(t), []upstream.Upstream{u})
require.Error(t, err)

assert.ErrorIs(t, err, errDesired)
Expand All @@ -38,73 +37,83 @@ func TestFastestAddr_ExchangeFastest(t *testing.T) {
// The alive IP is the just created local listener's address. The dead
// one is known as TEST-NET-1 which shouldn't be routed at all. See
// RFC-5737 (https://datatracker.ietf.org/doc/html/rfc5737).
aliveIP, deadIP := net.IP{127, 0, 0, 1}, net.IP{192, 0, 2, 1}
alive := new(testAUpstream).add(t.Name(), aliveIP)
dead := new(testAUpstream).add(t.Name(), deadIP)
aliveAddr := netip.MustParseAddr("127.0.0.1")

rep, up, err := f.ExchangeFastest(testARequest(t), []upstream.Upstream{dead, alive})
alive := &testAUpstream{
recs: []*dns.A{newTestRec(t, aliveAddr)},
}
dead := &testAUpstream{
recs: []*dns.A{newTestRec(t, netip.MustParseAddr("192.0.2.1"))},
}

rep, ups, err := f.ExchangeFastest(newTestReq(t), []upstream.Upstream{dead, alive})
require.NoError(t, err)

assert.Equal(t, up, alive)
assert.Equal(t, ups, alive)

require.NotNil(t, rep)
require.NotEmpty(t, rep.Answer)
require.IsType(t, new(dns.A), rep.Answer[0])

ip := rep.Answer[0].(*dns.A).A
assert.True(t, aliveIP.Equal(ip))
assert.Equal(t, aliveAddr.AsSlice(), []byte(ip))
})

t.Run("all_dead", func(t *testing.T) {
f := NewFastestAddr()
f.pingPorts = []uint{getFreePort(t)}

firstIP := net.IP{127, 0, 0, 1}
up1 := new(testAUpstream).
add(t.Name(), firstIP).
add(t.Name(), net.IP{127, 0, 0, 2}).
add(t.Name(), net.IP{127, 0, 0, 3})
firstIP := netip.MustParseAddr("127.0.0.1")
ups := &testAUpstream{
recs: []*dns.A{
newTestRec(t, firstIP),
newTestRec(t, netip.MustParseAddr("127.0.0.2")),
newTestRec(t, netip.MustParseAddr("127.0.0.3")),
},
}

resp, _, err := f.ExchangeFastest(testARequest(t), []upstream.Upstream{up1})
resp, _, err := f.ExchangeFastest(newTestReq(t), []upstream.Upstream{ups})
require.NoError(t, err)

require.NotNil(t, resp)
require.NotEmpty(t, resp.Answer)
require.IsType(t, new(dns.A), resp.Answer[0])

ip := resp.Answer[0].(*dns.A).A
assert.True(t, firstIP.Equal(ip))
assert.Equal(t, firstIP.AsSlice(), []byte(ip))
})
}

// testAUpstream is a mock err upstream structure for tests.
type errUpstream struct {
err error
closeErr error
}

// Address implements the [upstream.Upstream] interface for errUpstream.
// Address implements the [upstream.Upstream] interface for *errUpstream.
func (u *errUpstream) Address() string {
return "bad_upstream"
}

// Exchange implements the [upstream.Upstream] interface for errUpstream.
// Exchange implements the [upstream.Upstream] interface for *errUpstream.
func (u *errUpstream) Exchange(_ *dns.Msg) (*dns.Msg, error) {
return nil, u.err
}

// Close implements the [upstream.Upstream] interface for errUpstream.
// Close implements the [upstream.Upstream] interface for *errUpstream.
func (u *errUpstream) Close() error {
return u.closeErr
}

// testAUpstream is a mock A upstream structure for tests.
type testAUpstream struct {
recs []*dns.A
}

// type check
var _ upstream.Upstream = (*testAUpstream)(nil)

// Exchange implements the upstream.Upstream interface for *testAUpstream.
// Exchange implements the [upstream.Upstream] interface for *testAUpstream.
func (u *testAUpstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
resp = &dns.Msg{}
resp.SetReply(m)
Expand All @@ -116,30 +125,30 @@ func (u *testAUpstream) Exchange(m *dns.Msg) (resp *dns.Msg, err error) {
return resp, nil
}

// Address implements the upstream.Upstream interface for *testAUpstream.
// Address implements the [upstream.Upstream] interface for *testAUpstream.
func (u *testAUpstream) Address() (addr string) {
return ""
}

// Close implements the upstream.Upstream interface for *testAUpstream.
// Close implements the [upstream.Upstream] interface for *testAUpstream.
func (u *testAUpstream) Close() (err error) {
return nil
}

func (u *testAUpstream) add(host string, ip net.IP) (chain *testAUpstream) {
u.recs = append(u.recs, &dns.A{
// newTestRec returns a new test A record.
func newTestRec(t *testing.T, addr netip.Addr) (rr *dns.A) {
return &dns.A{
Hdr: dns.RR_Header{
Rrtype: dns.TypeA,
Name: dns.Fqdn(host),
Name: dns.Fqdn(t.Name()),
Ttl: 60,
},
A: ip,
})

return u
A: addr.AsSlice(),
}
}

func testARequest(t *testing.T) (req *dns.Msg) {
// newTestReq returns a new test A request.
func newTestReq(t *testing.T) (req *dns.Msg) {
return &dns.Msg{
MsgHdr: dns.MsgHdr{
Id: dns.Id(),
Expand Down
47 changes: 0 additions & 47 deletions internal/netutil/netutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,12 @@
package netutil

import (
"net"
"net/netip"
"strings"

glnetutil "github.com/AdguardTeam/golibs/netutil"
"golang.org/x/exp/slices"
)

// SortIPAddrs sorts addrs in accordance with the protocol preferences. Invalid
// addresses are sorted near the end. Zones are ignored.
//
// TODO(a.garipov): Use netip.Addr instead of net.IPAddr everywhere where this
// is called.
func SortIPAddrs(addrs []net.IPAddr, preferIPv6 bool) {
l := len(addrs)
if l <= 1 {
return
}

slices.SortStableFunc(addrs, func(addrA, addrB net.IPAddr) (res int) {
// Assume that len(addrs) is mostly small, so these conversions aren't
// as expensive as they could have been.
a, err := glnetutil.IPToAddrNoMapped(addrA.IP)
if err != nil {
return 1
}

b, err := glnetutil.IPToAddrNoMapped(addrB.IP)
if err != nil {
return -1
}

aIs4, bIs4 := a.Is4(), b.Is4()
if aIs4 == bIs4 {
return a.Compare(b)
}

if aIs4 {
if preferIPv6 {
return 1
}

return -1
}

if preferIPv6 {
return -1
}

return 1
})
}

// SortNetIPAddrs sorts addrs in accordance with the protocol preferences.
// Invalid addresses are sorted near the end. Zones are ignored.
func SortNetIPAddrs(addrs []netip.Addr, preferIPv6 bool) {
Expand Down
34 changes: 15 additions & 19 deletions internal/netutil/netutil_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,32 @@ package netutil_test

import (
"fmt"
"net"
"net/netip"

"github.com/AdguardTeam/dnsproxy/internal/netutil"
)

func ExampleSortIPAddrs() {
printAddrs := func(header string, addrs []net.IPAddr) {
func ExampleSortNetIPAddrs() {
printAddrs := func(header string, addrs []netip.Addr) {
fmt.Printf("%s:\n", header)
for i, a := range addrs {
fmt.Printf("%d: %s\n", i+1, a.IP)
fmt.Printf("%d: %s\n", i+1, a)
}

fmt.Println()
}

addrs := []net.IPAddr{{
IP: net.ParseIP("1.2.3.4"),
}, {
IP: net.ParseIP("1.2.3.5"),
}, {
IP: net.ParseIP("2a00::1234"),
}, {
IP: net.ParseIP("2a00::1235"),
}, {
IP: nil,
}}
netutil.SortIPAddrs(addrs, false)
addrs := []netip.Addr{
netip.MustParseAddr("1.2.3.4"),
netip.MustParseAddr("1.2.3.5"),
netip.MustParseAddr("2a00::1234"),
netip.MustParseAddr("2a00::1235"),
{},
}
netutil.SortNetIPAddrs(addrs, false)
printAddrs("IPv4 preferred", addrs)

netutil.SortIPAddrs(addrs, true)
netutil.SortNetIPAddrs(addrs, true)
printAddrs("IPv6 preferred", addrs)

// Output:
Expand All @@ -41,12 +37,12 @@ func ExampleSortIPAddrs() {
// 2: 1.2.3.5
// 3: 2a00::1234
// 4: 2a00::1235
// 5: <nil>
// 5: invalid IP
//
// IPv6 preferred:
// 1: 2a00::1234
// 2: 2a00::1235
// 3: 1.2.3.4
// 4: 1.2.3.5
// 5: <nil>
// 5: invalid IP
}
9 changes: 6 additions & 3 deletions internal/netutil/udp.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package netutil

import "net"
import (
"net"
"net/netip"
)

// UDPGetOOBSize returns maximum size of the received OOB data.
func UDPGetOOBSize() (oobSize int) {
Expand All @@ -22,7 +25,7 @@ func UDPRead(
conn *net.UDPConn,
buf []byte,
udpOOBSize int,
) (n int, localIP net.IP, remoteAddr *net.UDPAddr, err error) {
) (n int, localIP netip.Addr, remoteAddr *net.UDPAddr, err error) {
return udpRead(conn, buf, udpOOBSize)
}

Expand All @@ -33,7 +36,7 @@ func UDPWrite(
data []byte,
conn *net.UDPConn,
remoteAddr *net.UDPAddr,
localIP net.IP,
localIP netip.Addr,
) (n int, err error) {
return udpWrite(data, conn, remoteAddr, localIP)
}
21 changes: 13 additions & 8 deletions internal/netutil/udp_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ package netutil
import (
"fmt"
"net"
"net/netip"

"github.com/AdguardTeam/golibs/mathutil"
"github.com/AdguardTeam/golibs/netutil"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
Expand Down Expand Up @@ -39,33 +41,36 @@ func udpSetOptions(c *net.UDPConn) (err error) {
return nil
}

func udpGetDstFromOOB(oob []byte) (dst net.IP) {
func udpGetDstFromOOB(oob []byte) (dst netip.Addr, err error) {
cm6 := &ipv6.ControlMessage{}
if cm6.Parse(oob) == nil && cm6.Dst != nil {
return cm6.Dst
return netutil.IPToAddr(cm6.Dst, netutil.AddrFamilyIPv6)
}

cm4 := &ipv4.ControlMessage{}
if cm4.Parse(oob) == nil && cm4.Dst != nil {
return cm4.Dst
return netutil.IPToAddr(cm4.Dst, netutil.AddrFamilyIPv4)
}

return nil
return netip.Addr{}, nil
}

func udpRead(
c *net.UDPConn,
buf []byte,
udpOOBSize int,
) (n int, localIP net.IP, remoteAddr *net.UDPAddr, err error) {
) (n int, localIP netip.Addr, remoteAddr *net.UDPAddr, err error) {
var oobn int
oob := make([]byte, udpOOBSize)
n, oobn, _, remoteAddr, err = c.ReadMsgUDP(buf, oob)
if err != nil {
return -1, nil, nil, err
return -1, netip.Addr{}, nil, err
}

localIP = udpGetDstFromOOB(oob[:oobn])
localIP, err = udpGetDstFromOOB(oob[:oobn])
if err != nil {
return -1, netip.Addr{}, nil, err
}

return n, localIP, remoteAddr, nil
}
Expand All @@ -74,7 +79,7 @@ func udpWrite(
data []byte,
conn *net.UDPConn,
remoteAddr *net.UDPAddr,
localIP net.IP,
localIP netip.Addr,
) (n int, err error) {
n, _, err = conn.WriteMsgUDP(data, udpMakeOOBWithSrc(localIP), remoteAddr)

Expand Down
Loading

0 comments on commit 5eb940d

Please sign in to comment.