[netstack] absorb upstream changes
- replace some incorrect "piecemeal" types with tcpip.ProtocolAddress
- remove lots of netstack/util wrappers which aren't useful
- fix logging deadlocks in netstack/routes
- call tcpip.Endpoint.Disconnect on AF_UNSPEC
Change-Id: I5fad493f38c540581bf7f69b24ace5f52253af7b
diff --git a/src/connectivity/network/netstack/dhcp/client.go b/src/connectivity/network/netstack/dhcp/client.go
index 0efbaac..5e67ee5 100644
--- a/src/connectivity/network/netstack/dhcp/client.go
+++ b/src/connectivity/network/netstack/dhcp/client.go
@@ -9,9 +9,9 @@
"context"
"fmt"
"math"
+ "net"
"time"
- "netstack/util"
"syslog"
"github.com/google/netstack/rand"
@@ -350,12 +350,13 @@
c.server = cfg.ServerAddress
if len(cfg.SubnetMask) == 0 {
- cfg.SubnetMask = util.DefaultMask(c.addr.Address)
+ cfg.SubnetMask = tcpip.AddressMask(net.IP(c.addr.Address).DefaultMask())
}
+ prefixLen, _ := net.IPMask(cfg.SubnetMask).Size()
requestedAddr = tcpip.AddressWithPrefix{
Address: addr,
- PrefixLen: util.PrefixLength(cfg.SubnetMask),
+ PrefixLen: prefixLen,
}
syslog.VLogTf(syslog.DebugVerbosity, tag, "got %s from %s: Address=%s, server=%s, leaseTime=%s, renewalTime=%s, rebindTime=%s", typ, srcAddr.Addr, requestedAddr, c.server, cfg.LeaseLength, cfg.RenewalTime, cfg.RebindingTime)
@@ -400,9 +401,10 @@
if err := cfg.decode(opts); err != nil {
return Config{}, fmt.Errorf("%s decode: %s", typ, err)
}
+ prefixLen, _ := net.IPMask(cfg.SubnetMask).Size()
addr := tcpip.AddressWithPrefix{
Address: addr,
- PrefixLen: util.PrefixLength(cfg.SubnetMask),
+ PrefixLen: prefixLen,
}
if addr != requestedAddr {
return Config{}, fmt.Errorf("%s with unexpected address=%s expected=%s", typ, addr, requestedAddr)
diff --git a/src/connectivity/network/netstack/dhcp/dhcp_test.go b/src/connectivity/network/netstack/dhcp/dhcp_test.go
index 5eae7e2..660fb18 100644
--- a/src/connectivity/network/netstack/dhcp/dhcp_test.go
+++ b/src/connectivity/network/netstack/dhcp/dhcp_test.go
@@ -6,7 +6,6 @@
import (
"context"
- "strings"
"sync/atomic"
"testing"
"time"
@@ -59,9 +58,7 @@
}
s.SetRouteTable([]tcpip.Route{{
- Destination: tcpip.Address(strings.Repeat("\x00", 4)),
- Mask: tcpip.AddressMask(strings.Repeat("\x00", 4)),
- Gateway: "",
+ Destination: tcpipHeader.IPv4EmptySubnet,
NIC: nicid,
}})
diff --git a/src/connectivity/network/netstack/fidlconv/fidlconv.go b/src/connectivity/network/netstack/fidlconv/fidlconv.go
index 2386c5f..5556bc0 100644
--- a/src/connectivity/network/netstack/fidlconv/fidlconv.go
+++ b/src/connectivity/network/netstack/fidlconv/fidlconv.go
@@ -5,31 +5,30 @@
package fidlconv
import (
- "bytes"
- "encoding/binary"
"fmt"
- "math/big"
"net"
- "netstack/util"
-
netfidl "fidl/fuchsia/net"
"fidl/fuchsia/net/stack"
"github.com/google/netstack/tcpip"
)
-func ToTCPIPAddress(addr netfidl.IpAddress) tcpip.Address {
+func toNet(addr netfidl.IpAddress) net.IP {
switch tag := addr.Which(); tag {
case netfidl.IpAddressIpv4:
- return tcpip.Address(addr.Ipv4.Addr[:])
+ return addr.Ipv4.Addr[:]
case netfidl.IpAddressIpv6:
- return tcpip.Address(addr.Ipv6.Addr[:])
+ return addr.Ipv6.Addr[:]
default:
panic(fmt.Sprintf("invalid IP address tag = %d", tag))
}
}
+func ToTCPIPAddress(addr netfidl.IpAddress) tcpip.Address {
+ return tcpip.Address(toNet(addr))
+}
+
func ToNetIpAddress(addr tcpip.Address) netfidl.IpAddress {
var out netfidl.IpAddress
switch l := len(addr); l {
@@ -47,82 +46,43 @@
return out
}
-func ToTCPIPSubnet(sn netfidl.Subnet) (tcpip.Subnet, error) {
- // Use ToTCPIPAddress to abstract the IPv4 vs IPv6 behavior.
- a := []byte(ToTCPIPAddress(sn.Addr))
- m := util.CIDRMask(int(sn.PrefixLen), int(len(a)*8))
- for i := range a {
- a[i] = a[i] & m[i]
+func ToTCPIPSubnet(sn netfidl.Subnet) tcpip.Subnet {
+ a := toNet(sn.Addr)
+ m := net.CIDRMask(int(sn.PrefixLen), len(a)*8)
+ subnet, err := tcpip.NewSubnet(tcpip.Address(a.Mask(m)), tcpip.AddressMask(m))
+ if err != nil {
+ panic(err)
}
- return tcpip.NewSubnet(tcpip.Address(a), m)
+ return subnet
}
-func GetPrefixLen(mask tcpip.AddressMask) uint8 {
- prefixLen := uint8(0)
- switch len(mask) {
- case 4:
- var x uint32
- if err := binary.Read(bytes.NewReader([]byte(mask)), binary.BigEndian, &x); err != nil {
- return 0
- }
- if x == 0 {
- return 0
- }
- for x&1 == 0 {
- prefixLen += 1
- x >>= 1
- }
- return 32 - prefixLen
- case 16:
- var x big.Int
- zero := big.NewInt(0)
- one := big.NewInt(1)
- x.SetBytes([]byte(mask))
-
- if x.Cmp(zero) == 0 {
- return 0
- }
- var tmp big.Int
- for tmp.And(&x, one).Cmp(zero) == 0 {
- prefixLen += 1
- x.Rsh(&x, 1)
- }
- return 128 - prefixLen
- default:
- panic("invalid tcpip.Address length")
+func TcpipRouteToForwardingEntry(route tcpip.Route) stack.ForwardingEntry {
+ forwardingEntry := stack.ForwardingEntry{
+ Subnet: netfidl.Subnet{
+ Addr: ToNetIpAddress(route.Destination.ID()),
+ PrefixLen: uint8(route.Destination.Prefix()),
+ },
}
-}
-
-func TcpipRouteToForwardingEntry(tcpipRoute tcpip.Route) stack.ForwardingEntry {
- var dest stack.ForwardingDestination
// There are two types of destinations: link-local and next-hop.
// If a route has a gateway, use that as the next-hop, and ignore the NIC.
// Otherwise, it is considered link-local, and use the NIC.
- if tcpipRoute.Gateway == tcpip.Address("") {
- dest.SetDeviceId(uint64(tcpipRoute.NIC))
+ if len(route.Gateway) == 0 {
+ forwardingEntry.Destination.SetDeviceId(uint64(route.NIC))
} else {
- dest.SetNextHop(ToNetIpAddress(tcpipRoute.Gateway))
+ forwardingEntry.Destination.SetNextHop(ToNetIpAddress(route.Gateway))
}
- return stack.ForwardingEntry{
- Subnet: netfidl.Subnet{
- Addr: ToNetIpAddress(tcpipRoute.Destination),
- PrefixLen: GetPrefixLen(tcpipRoute.Mask),
- },
- Destination: dest,
- }
+ return forwardingEntry
}
func ForwardingEntryToTcpipRoute(forwardingEntry stack.ForwardingEntry) tcpip.Route {
- dest := ToTCPIPAddress(forwardingEntry.Subnet.Addr)
- tcpipRoute := tcpip.Route{
- Destination: dest,
- Mask: util.CIDRMask(int(forwardingEntry.Subnet.PrefixLen), len(dest)*8),
+ route := tcpip.Route{
+ Destination: ToTCPIPSubnet(forwardingEntry.Subnet),
}
switch forwardingEntry.Destination.Which() {
case stack.ForwardingDestinationDeviceId:
- tcpipRoute.NIC = tcpip.NICID(forwardingEntry.Destination.DeviceId)
+ route.NIC = tcpip.NICID(forwardingEntry.Destination.DeviceId)
case stack.ForwardingDestinationNextHop:
- tcpipRoute.Gateway = ToTCPIPAddress(forwardingEntry.Destination.NextHop)
+ route.Gateway = ToTCPIPAddress(forwardingEntry.Destination.NextHop)
}
- return tcpipRoute
+ return route
}
diff --git a/src/connectivity/network/netstack/fidlconv/fidlconv_test.go b/src/connectivity/network/netstack/fidlconv/fidlconv_test.go
index 9cc4a34..fa5fb36 100644
--- a/src/connectivity/network/netstack/fidlconv/fidlconv_test.go
+++ b/src/connectivity/network/netstack/fidlconv/fidlconv_test.go
@@ -5,11 +5,12 @@
package fidlconv
import (
+ "net"
"testing"
"netstack/util"
- "fidl/fuchsia/net"
+ fidlnet "fidl/fuchsia/net"
"fidl/fuchsia/net/stack"
"github.com/google/netstack/tcpip"
@@ -19,8 +20,8 @@
// This is challenging because of the way FIDL unions are constructed in Go.
func TestNetIPtoTCPIPAddressIPv4(t *testing.T) {
- from := net.IpAddress{}
- from.SetIpv4(net.Ipv4Address{Addr: [4]uint8{127, 0, 0, 1}})
+ from := fidlnet.IpAddress{}
+ from.SetIpv4(fidlnet.Ipv4Address{Addr: [4]uint8{127, 0, 0, 1}})
to := ToTCPIPAddress(from)
expected := util.Parse("127.0.0.1")
if to != expected {
@@ -29,8 +30,8 @@
}
func TestNetIPtoTCPIPAddressIPv6(t *testing.T) {
- from := net.IpAddress{}
- from.SetIpv6(net.Ipv6Address{Addr: [16]uint8{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}})
+ from := fidlnet.IpAddress{}
+ from.SetIpv6(fidlnet.Ipv6Address{Addr: [16]uint8{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}})
to := ToTCPIPAddress(from)
expected := util.Parse("fe80::1")
if to != expected {
@@ -41,8 +42,8 @@
func TestToFIDLIPAddressIPv4(t *testing.T) {
from := util.Parse("127.0.0.1")
to := ToNetIpAddress(from)
- expected := net.IpAddress{}
- expected.SetIpv4(net.Ipv4Address{Addr: [4]uint8{127, 0, 0, 1}})
+ expected := fidlnet.IpAddress{}
+ expected.SetIpv4(fidlnet.Ipv4Address{Addr: [4]uint8{127, 0, 0, 1}})
if to != expected {
t.Fatalf("Expected:\n %v\nActual:\n %v", expected, to)
}
@@ -51,8 +52,8 @@
func TestToFIDLIPAddressIPv6(t *testing.T) {
from := util.Parse("fe80::1")
to := ToNetIpAddress(from)
- expected := net.IpAddress{}
- expected.SetIpv6(net.Ipv6Address{Addr: [16]uint8{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}})
+ expected := fidlnet.IpAddress{}
+ expected.SetIpv6(fidlnet.Ipv6Address{Addr: [16]uint8{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}})
if to != expected {
t.Fatalf("Expected:\n %v\nActual:\n %v", expected, to)
}
@@ -96,16 +97,19 @@
{[4]uint8{0, 0, 0, 0}, 0, "0.0.0.0/0"},
}
for _, testCase := range cases {
- netSubnet := newNetSubnet(testCase.addr, testCase.prefix)
- to, err := ToTCPIPSubnet(netSubnet)
- if err != nil {
- t.Errorf("Error generating tcpip.Subnet: %v", err)
- continue
+ netSubnet := fidlnet.Subnet{
+ PrefixLen: testCase.prefix,
}
- _, expected, err := util.ParseCIDR(testCase.expected)
+ netSubnet.Addr.SetIpv4(fidlnet.Ipv4Address{Addr: testCase.addr})
+ to := ToTCPIPSubnet(netSubnet)
+ _, ipNet, err := net.ParseCIDR(testCase.expected)
if err != nil {
t.Fatalf("Error creating tcpip.Subnet: %v", err)
}
+ expected, err := tcpip.NewSubnet(tcpip.Address(ipNet.IP), tcpip.AddressMask(ipNet.Mask))
+ if err != nil {
+ t.Fatal(err)
+ }
if to != expected {
t.Errorf("Expected:\n {%v, %v}\nActual: {%v, %v}",
[]byte(expected.ID()), []byte(expected.Mask()),
@@ -114,70 +118,13 @@
}
}
-func TestPrefixLenIPv4(t *testing.T) {
- cases := []struct {
- mask tcpip.AddressMask
- prefix uint8
- }{
- {tcpip.AddressMask(util.Parse("255.255.255.255")), 32},
- {tcpip.AddressMask(util.Parse("255.255.255.254")), 31},
- {tcpip.AddressMask(util.Parse("255.255.255.128")), 25},
- {tcpip.AddressMask(util.Parse("255.255.255.0")), 24},
- {tcpip.AddressMask(util.Parse("255.0.0.0")), 8},
- {tcpip.AddressMask(util.Parse("128.0.0.0")), 1},
- {tcpip.AddressMask(util.Parse("0.0.0.0")), 0},
- }
- for _, testCase := range cases {
- prefixLen := GetPrefixLen(testCase.mask)
- if prefixLen != testCase.prefix {
- t.Errorf("Expected:\n %v\nActual: %v", testCase.prefix, prefixLen)
- }
- }
-}
-
-func TestPrefixLenIPv6(t *testing.T) {
- cases := []struct {
- mask tcpip.AddressMask
- prefix uint8
- }{
- {tcpip.AddressMask(util.Parse("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")), 128},
- {tcpip.AddressMask(util.Parse("ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000")), 113},
- {tcpip.AddressMask(util.Parse("ffff:ffff:ffff:ffff:ffff:ffff:ffff::")), 112},
- {tcpip.AddressMask(util.Parse("ffff:ffff:ffff:ffff:ffff:ffff:fffe::")), 111},
- {tcpip.AddressMask(util.Parse("8000::")), 1},
- {tcpip.AddressMask(util.Parse("::")), 0},
- }
- for _, testCase := range cases {
- prefixLen := GetPrefixLen(testCase.mask)
- if prefixLen != testCase.prefix {
- t.Errorf("Case: %v\n Expected:\n %v\nActual: %v", testCase.mask, testCase.prefix, prefixLen)
- }
- }
-}
-
-func TestPrefixLenEmptyInvalid(t *testing.T) {
- defer func() {
- if r := recover(); r == nil {
- t.Fatalf("Expected to fail on invalid address length")
- }
- }()
-
- GetPrefixLen("")
- t.Errorf("Expected to fail on invalid address length")
-}
-
-func TestPrefixLenInvalidLength(t *testing.T) {
- defer func() {
- if r := recover(); r == nil {
- t.Fatalf("Expected to fail on invalid address length")
- }
- }()
-
- GetPrefixLen("\x00\x00")
- t.Errorf("Expected to fail on invalid address length")
-}
-
func TestForwardingEntryAndTcpipRouteConversions(t *testing.T) {
+ const gateway = "efghijklmnopqrst"
+
+ destination, err := tcpip.NewSubnet("\xab\xcd\x00\x00", "\xff\xff\xe0\x00")
+ if err != nil {
+ t.Fatal(err)
+ }
for _, tc := range []struct {
dest stack.ForwardingDestination
want tcpip.Route
@@ -188,24 +135,22 @@
return dest
}(),
want: tcpip.Route{
- Destination: tcpip.Address("abcd"),
- Mask: "\xff\xff\xe0\x00",
+ Destination: destination,
NIC: 789,
}},
{dest: func() stack.ForwardingDestination {
var dest stack.ForwardingDestination
- dest.SetNextHop(ToNetIpAddress(tcpip.Address("efghijklmnopqrst")))
+ dest.SetNextHop(ToNetIpAddress(gateway))
return dest
}(),
want: tcpip.Route{
- Destination: tcpip.Address("abcd"),
- Mask: "\xff\xff\xe0\x00",
- Gateway: tcpip.Address("efghijklmnopqrst"),
+ Destination: destination,
+ Gateway: gateway,
}},
} {
fe := stack.ForwardingEntry{
- Subnet: net.Subnet{
- Addr: ToNetIpAddress(tcpip.Address("abcd")),
+ Subnet: fidlnet.Subnet{
+ Addr: ToNetIpAddress(destination.ID()),
PrefixLen: 19,
},
Destination: tc.dest,
@@ -220,10 +165,3 @@
}
}
}
-
-func newNetSubnet(addr [4]uint8, prefix uint8) net.Subnet {
- subnet := net.Subnet{}
- subnet.Addr.SetIpv4(net.Ipv4Address{Addr: addr})
- subnet.PrefixLen = prefix
- return subnet
-}
diff --git a/src/connectivity/network/netstack/filter/fidlconv.go b/src/connectivity/network/netstack/filter/fidlconv.go
index 8805d12..1cb08df 100644
--- a/src/connectivity/network/netstack/filter/fidlconv.go
+++ b/src/connectivity/network/netstack/filter/fidlconv.go
@@ -5,10 +5,9 @@
package filter
import (
- "netstack/util"
-
"fidl/fuchsia/net"
"fidl/fuchsia/net/filter"
+ "netstack/fidlconv"
"github.com/google/netstack/tcpip"
"github.com/google/netstack/tcpip/header"
@@ -137,16 +136,6 @@
}, nil
}
-func toSubnet(o *net.Subnet) (tcpip.Subnet, error) {
- addr, err := toAddress(&o.Addr)
- if err != nil {
- return tcpip.Subnet{}, ErrBadAddress
- }
- mask := util.CIDRMask(int(o.PrefixLen), 8*len(addr))
- subnet, err := tcpip.NewSubnet(addr, mask)
- return subnet, err
-}
-
func fromRule(o *Rule) (filter.Rule, error) {
action, err := fromAction(o.action)
if err != nil {
@@ -207,17 +196,11 @@
}
var srcSubnet, dstSubnet *tcpip.Subnet
if o.SrcSubnet != nil {
- subnet, err := toSubnet(o.SrcSubnet)
- if err != nil {
- return Rule{}, err
- }
+ subnet := fidlconv.ToTCPIPSubnet(*o.SrcSubnet)
srcSubnet = &subnet
}
if o.DstSubnet != nil {
- subnet, err := toSubnet(o.DstSubnet)
- if err != nil {
- return Rule{}, err
- }
+ subnet := fidlconv.ToTCPIPSubnet(*o.DstSubnet)
dstSubnet = &subnet
}
return Rule{
@@ -287,14 +270,11 @@
if err != nil {
return NAT{}, err
}
- srcSubnet, err := toSubnet(&o.SrcSubnet)
- if err != nil {
- return NAT{}, err
- }
newSrcAddr, err := toAddress(&o.NewSrcAddr)
if err != nil {
return NAT{}, err
}
+ srcSubnet := fidlconv.ToTCPIPSubnet(o.SrcSubnet)
return NAT{
transProto: transProto,
srcSubnet: &srcSubnet,
diff --git a/src/connectivity/network/netstack/filter/fidlconv_test.go b/src/connectivity/network/netstack/filter/fidlconv_test.go
index b96fe6f..fa9a83b 100644
--- a/src/connectivity/network/netstack/filter/fidlconv_test.go
+++ b/src/connectivity/network/netstack/filter/fidlconv_test.go
@@ -5,12 +5,13 @@
package filter
import (
+ "net"
"reflect"
"testing"
"netstack/util"
- "fidl/fuchsia/net"
+ fidlnet "fidl/fuchsia/net"
"fidl/fuchsia/net/filter"
"github.com/google/netstack/tcpip"
@@ -177,25 +178,25 @@
func TestFromAddress(t *testing.T) {
a1 := util.Parse("1.2.3.4")
- var b1 net.IpAddress
+ var b1 fidlnet.IpAddress
- b1.SetIpv4(net.Ipv4Address{Addr: [4]uint8{1, 2, 3, 4}})
+ b1.SetIpv4(fidlnet.Ipv4Address{Addr: [4]uint8{1, 2, 3, 4}})
a2 := util.Parse("a:b:c::2:3:4")
- var b2v6 net.Ipv6Address
+ var b2v6 fidlnet.Ipv6Address
copy(b2v6.Addr[:], "\x00\x0a\x00\x0b\x00\x0c\x00\x00\x00\x00\x00\x02\x00\x03\x00\x04")
- var b2 net.IpAddress
+ var b2 fidlnet.IpAddress
b2.SetIpv6(b2v6)
var tests = []struct {
address tcpip.Address
- netAddress net.IpAddress
+ netAddress fidlnet.IpAddress
err error
}{
{a1, b1, nil},
{a2, b2, nil},
- {tcpip.Address("12345"), net.IpAddress{}, ErrUnknownAddressType},
+ {tcpip.Address("12345"), fidlnet.IpAddress{}, ErrUnknownAddressType},
}
for _, test := range tests {
@@ -211,11 +212,11 @@
t.Errorf("fromAddress got.Which()=%v, want.Which()=%v", got.Which(), want.Which())
}
switch got.Which() {
- case net.IpAddressIpv4:
+ case fidlnet.IpAddressIpv4:
if got.Ipv4 != want.Ipv4 {
t.Errorf("fromAddress got.Ipv4=%v, want.Ipv4=%v", got.Ipv4, want.Ipv4)
}
- case net.IpAddressIpv6:
+ case fidlnet.IpAddressIpv6:
if got.Ipv6 != want.Ipv6 {
t.Errorf("fromAddress got.Ipv6=%v, want.Ipv6=%v", got.Ipv6, want.Ipv6)
}
@@ -226,26 +227,26 @@
}
func TestToAddress(t *testing.T) {
- var a1 net.IpAddress
- a1.SetIpv4(net.Ipv4Address{Addr: [4]uint8{1, 2, 3, 4}})
+ var a1 fidlnet.IpAddress
+ a1.SetIpv4(fidlnet.Ipv4Address{Addr: [4]uint8{1, 2, 3, 4}})
b1 := util.Parse("1.2.3.4")
- var a2v6 net.Ipv6Address
+ var a2v6 fidlnet.Ipv6Address
copy(a2v6.Addr[:], "\x00\x0a\x00\x0b\x00\x0c\x00\x00\x00\x00\x00\x02\x00\x03\x00\x04")
- var a2 net.IpAddress
+ var a2 fidlnet.IpAddress
a2.SetIpv6(a2v6)
b2 := util.Parse("a:b:c::2:3:4")
var tests = []struct {
- netAddress net.IpAddress
+ netAddress fidlnet.IpAddress
address tcpip.Address
err error
}{
{a1, b1, nil},
{a2, b2, nil},
- {net.IpAddress{}, tcpip.Address(""), ErrUnknownAddressType},
+ {fidlnet.IpAddress{}, tcpip.Address(""), ErrUnknownAddressType},
}
for _, test := range tests {
@@ -262,42 +263,50 @@
}
}
+func parseCIDR(s string) (tcpip.Subnet, error) {
+ _, subnet, err := net.ParseCIDR(s)
+ if err != nil {
+ return tcpip.Subnet{}, err
+ }
+ return tcpip.NewSubnet(tcpip.Address(subnet.IP), tcpip.AddressMask(subnet.Mask))
+}
+
func TestFromSubnet(t *testing.T) {
// test1
- _, s1, err := util.ParseCIDR("1.2.3.4/32")
+ s1, err := parseCIDR("1.2.3.4/32")
if err != nil {
t.Errorf("ParseCIDR error: %v", err)
}
- var a1 net.IpAddress
- a1.SetIpv4(net.Ipv4Address{Addr: [4]uint8{1, 2, 3, 4}})
- t1 := net.Subnet{Addr: a1, PrefixLen: 32}
+ var a1 fidlnet.IpAddress
+ a1.SetIpv4(fidlnet.Ipv4Address{Addr: [4]uint8{1, 2, 3, 4}})
+ t1 := fidlnet.Subnet{Addr: a1, PrefixLen: 32}
// test2
- _, s2, err := util.ParseCIDR("10.0.0.0/8")
+ s2, err := parseCIDR("10.0.0.0/8")
if err != nil {
t.Errorf("ParseCIDR error: %v", err)
}
- var a2 net.IpAddress
- a2.SetIpv4(net.Ipv4Address{Addr: [4]uint8{10, 0, 0, 0}})
- t2 := net.Subnet{Addr: a2, PrefixLen: 8}
+ var a2 fidlnet.IpAddress
+ a2.SetIpv4(fidlnet.Ipv4Address{Addr: [4]uint8{10, 0, 0, 0}})
+ t2 := fidlnet.Subnet{Addr: a2, PrefixLen: 8}
// test3
- _, s3, err := util.ParseCIDR("a:b:c::/96")
+ s3, err := parseCIDR("a:b:c::/96")
if err != nil {
t.Errorf("ParseCIDR error: %v", err)
}
- var a3v6 net.Ipv6Address
+ var a3v6 fidlnet.Ipv6Address
copy(a3v6.Addr[:], "\x00\x0a\x00\x0b\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
- var a3 net.IpAddress
+ var a3 fidlnet.IpAddress
a3.SetIpv6(a3v6)
- t3 := net.Subnet{Addr: a3, PrefixLen: 96}
+ t3 := fidlnet.Subnet{Addr: a3, PrefixLen: 96}
var tests = []struct {
subnet tcpip.Subnet
- netSubnet net.Subnet
+ netSubnet fidlnet.Subnet
err error
}{
{s1, t1, nil},
@@ -318,11 +327,11 @@
t.Errorf("fromSubnet got.Addr.Which()=%v, want.Addr.Which()=%v", got.Addr.Which(), want.Addr.Which())
}
switch got.Addr.Which() {
- case net.IpAddressIpv4:
+ case fidlnet.IpAddressIpv4:
if got.Addr.Ipv4 != want.Addr.Ipv4 {
t.Errorf("fromSubnet got.Addr.Ipv4=%v, want.Addr.Ipv4=%v", got.Addr.Ipv4, want.Addr.Ipv4)
}
- case net.IpAddressIpv6:
+ case fidlnet.IpAddressIpv6:
if got.Addr.Ipv6 != want.Addr.Ipv6 {
t.Errorf("fromSubnet got.Addr.Ipv6=%v, want.Addr.Ipv6=%v", got.Addr.Ipv6, want.Addr.Ipv6)
}
@@ -335,73 +344,12 @@
}
}
-func TestToSubnet(t *testing.T) {
- // test1
- var a1 net.IpAddress
- a1.SetIpv4(net.Ipv4Address{Addr: [4]uint8{1, 2, 3, 4}})
- s1 := net.Subnet{Addr: a1, PrefixLen: 32}
-
- _, t1, err := util.ParseCIDR("1.2.3.4/32")
- if err != nil {
- t.Errorf("ParseCIDR error: %v", err)
- }
-
- // test2
- var a2 net.IpAddress
- a2.SetIpv4(net.Ipv4Address{Addr: [4]uint8{10, 0, 0, 0}})
- s2 := net.Subnet{Addr: a2, PrefixLen: 8}
-
- _, t2, err := util.ParseCIDR("10.0.0.0/8")
- if err != nil {
- t.Errorf("ParseCIDR error: %v", err)
- }
-
- // test3
- var a3v6 net.Ipv6Address
- copy(a3v6.Addr[:], "\x00\x0a\x00\x0b\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
- var a3 net.IpAddress
- a3.SetIpv6(a3v6)
- s3 := net.Subnet{Addr: a3, PrefixLen: 96}
-
- _, t3, err := util.ParseCIDR("a:b:c::/96")
- if err != nil {
- t.Errorf("ParseCIDR error: %v", err)
- }
-
- var tests = []struct {
- netSubnet net.Subnet
- subnet tcpip.Subnet
- err error
- }{
- {s1, t1, nil},
- {s2, t2, nil},
- {s3, t3, nil},
- }
-
- for _, test := range tests {
- subnet, err := toSubnet(&test.netSubnet)
- if err != test.err {
- t.Errorf("toSubnet unxpected error: %v", err)
- }
- if err != nil {
- continue
- }
- got, want := subnet, test.subnet
- if got.ID() != want.ID() {
- t.Errorf("toSubnet got.ID()=%v, want.ID()=%v", got.ID(), want.ID())
- }
- if got.Mask() != want.Mask() {
- t.Errorf("toSubnet got.Mask()=%x, want.Mask()=%x", got.Mask(), want.Mask())
- }
- }
-}
-
func TestRules(t *testing.T) {
- _, srcSubnet, err := util.ParseCIDR("1.2.3.4/32")
+ srcSubnet, err := parseCIDR("1.2.3.4/32")
if err != nil {
t.Errorf("ParseCIDR error: %v", err)
}
- _, dstSubnet, err := util.ParseCIDR("5.6.7.8/32")
+ dstSubnet, err := parseCIDR("5.6.7.8/32")
if err != nil {
t.Errorf("ParseCIDR error: %v", err)
}
@@ -474,7 +422,7 @@
}
func TestNATs(t *testing.T) {
- _, srcSubnet, err := util.ParseCIDR("1.2.3.4/32")
+ srcSubnet, err := parseCIDR("1.2.3.4/32")
if err != nil {
t.Errorf("ParseCIDR error: %v", err)
}
diff --git a/src/connectivity/network/netstack/filter/nat_test.go b/src/connectivity/network/netstack/filter/nat_test.go
index b13d1a6..f9c24ac 100644
--- a/src/connectivity/network/netstack/filter/nat_test.go
+++ b/src/connectivity/network/netstack/filter/nat_test.go
@@ -19,12 +19,17 @@
// TODO: make these tests table-driven.
-var (
- testLanNet = util.Parse("192.168.42.0")
- testLanNetMask tcpip.AddressMask = "\xff\xff\xff\x00"
+func makeSubnet(addr string, m tcpip.AddressMask) tcpip.Subnet {
+ subnet, err := tcpip.NewSubnet(util.Parse(addr), m)
+ if err != nil {
+ panic(err)
+ }
+ return subnet
+}
- testWanNet = util.Parse("10.0.0.0")
- testWanNetMask tcpip.AddressMask = "\xff\x00\x00\x00"
+var (
+ testLanNet = makeSubnet("192.168.42.0", "\xff\xff\xff\x00")
+ testWanNet = makeSubnet("10.0.0.0", "\xff\x00\x00\x00")
testLanNICAddr = util.Parse("192.168.42.10")
testRouterNICAddr1 = util.Parse("192.168.42.1")
@@ -58,12 +63,10 @@
s.SetRouteTable([]tcpip.Route{
{
Destination: testLanNet,
- Mask: testLanNetMask,
NIC: nic,
},
{
Destination: testWanNet,
- Mask: testWanNetMask,
NIC: nic,
},
})
@@ -82,7 +85,6 @@
s.SetRouteTable([]tcpip.Route{
{
Destination: testWanNet,
- Mask: testWanNetMask,
NIC: nic,
},
})
@@ -93,20 +95,16 @@
s := stack.New([]string{ipv4.ProtocolName}, []string{udp.ProtocolName, tcp.ProtocolName}, stack.Options{})
f := New(s.PortManager)
- srcSubnet, terr := tcpip.NewSubnet(testLanNet, tcpip.AddressMask(testLanNetMask))
- if terr != nil {
- t.Fatalf("NewSubnet error: %s", terr)
- }
f.rulesetNAT.Lock()
f.rulesetNAT.v = []NAT{
{
transProto: header.UDPProtocolNumber,
- srcSubnet: &srcSubnet,
+ srcSubnet: &testLanNet,
newSrcAddr: testRouterNICAddr2,
},
{
transProto: header.TCPProtocolNumber,
- srcSubnet: &srcSubnet,
+ srcSubnet: &testLanNet,
newSrcAddr: testRouterNICAddr2,
},
}
@@ -133,12 +131,10 @@
s.SetRouteTable([]tcpip.Route{
{
Destination: testLanNet,
- Mask: testLanNetMask,
NIC: nic1,
},
{
Destination: testWanNet,
- Mask: testWanNetMask,
NIC: nic2,
},
})
diff --git a/src/connectivity/network/netstack/filter/rdr_test.go b/src/connectivity/network/netstack/filter/rdr_test.go
index c06c633..926fd04 100644
--- a/src/connectivity/network/netstack/filter/rdr_test.go
+++ b/src/connectivity/network/netstack/filter/rdr_test.go
@@ -60,12 +60,10 @@
s.SetRouteTable([]tcpip.Route{
{
Destination: testLanNet,
- Mask: testLanNetMask,
NIC: nic1,
},
{
Destination: testWanNet,
- Mask: testWanNetMask,
NIC: nic2,
},
})
diff --git a/src/connectivity/network/netstack/fuchsia_net_stack.go b/src/connectivity/network/netstack/fuchsia_net_stack.go
index b8204e9..8762f9a 100644
--- a/src/connectivity/network/netstack/fuchsia_net_stack.go
+++ b/src/connectivity/network/netstack/fuchsia_net_stack.go
@@ -138,19 +138,43 @@
if enabled {
if err := ifs.eth.Up(); err != nil {
- syslog.Errorf("ifs.eth.Up() failed (NIC %d): %v", id, err)
+ syslog.Errorf("ifs.eth.Up() failed (NIC %d): %s", id, err)
return &stack.Error{Type: stack.ErrorTypeInternal}
}
} else {
if err := ifs.eth.Down(); err != nil {
- syslog.Errorf("ifs.eth.Down() failed (NIC %d): %v", id, err)
+ syslog.Errorf("ifs.eth.Down() failed (NIC %d): %s", id, err)
return &stack.Error{Type: stack.ErrorTypeInternal}
}
}
return nil
}
+func toProtocolAddr(ifAddr stack.InterfaceAddress) tcpip.ProtocolAddress {
+ protocolAddr := tcpip.ProtocolAddress{
+ AddressWithPrefix: tcpip.AddressWithPrefix{
+ PrefixLen: int(ifAddr.PrefixLen),
+ },
+ }
+
+ switch typ := ifAddr.IpAddress.Which(); typ {
+ case net.IpAddressIpv4:
+ protocolAddr.Protocol = ipv4.ProtocolNumber
+ protocolAddr.AddressWithPrefix.Address = tcpip.Address(ifAddr.IpAddress.Ipv4.Addr[:])
+ case net.IpAddressIpv6:
+ protocolAddr.Protocol = ipv6.ProtocolNumber
+ protocolAddr.AddressWithPrefix.Address = tcpip.Address(ifAddr.IpAddress.Ipv6.Addr[:])
+ default:
+ panic(fmt.Sprintf("unknown IpAddress type %d", typ))
+ }
+ return protocolAddr
+}
+
func (ns *Netstack) addInterfaceAddr(id uint64, ifAddr stack.InterfaceAddress) *stack.Error {
+ protocolAddr := toProtocolAddr(ifAddr)
+ if protocolAddr.AddressWithPrefix.PrefixLen > 8*len(protocolAddr.AddressWithPrefix.Address) {
+ return &stack.Error{Type: stack.ErrorTypeInvalidArgs}
+ }
nicid := tcpip.NICID(id)
ns.mu.Lock()
@@ -161,44 +185,30 @@
return &stack.Error{Type: stack.ErrorTypeNotFound}
}
- var protocol tcpip.NetworkProtocolNumber
- switch typ := ifAddr.IpAddress.Which(); typ {
- case net.IpAddressIpv4:
- protocol = ipv4.ProtocolNumber
- case net.IpAddressIpv6:
- protocol = ipv6.ProtocolNumber
- default:
- panic(fmt.Sprintf("unknown IpAddress type %d", typ))
- }
-
- if err := ns.addInterfaceAddress(nicid, protocol, fidlconv.ToTCPIPAddress(ifAddr.IpAddress), ifAddr.PrefixLen); err != nil {
- syslog.Errorf("(*Netstack).setInterfaceAddress(...) failed (NIC %d): %v", nicid, err)
+ if err := ns.addInterfaceAddress(nicid, protocolAddr); err != nil {
+ syslog.Errorf("(*Netstack).addInterfaceAddr(%s) failed (NIC %d): %s", protocolAddr.AddressWithPrefix, nicid, err)
return &stack.Error{Type: stack.ErrorTypeBadState}
}
return nil
}
-func (ns *Netstack) delInterfaceAddr(id uint64, addr stack.InterfaceAddress) *stack.Error {
+func (ns *Netstack) delInterfaceAddr(id uint64, ifAddr stack.InterfaceAddress) *stack.Error {
+ protocolAddr := toProtocolAddr(ifAddr)
+ if protocolAddr.AddressWithPrefix.PrefixLen > 8*len(protocolAddr.AddressWithPrefix.Address) {
+ return &stack.Error{Type: stack.ErrorTypeInvalidArgs}
+ }
+ nicid := tcpip.NICID(id)
+
ns.mu.Lock()
- _, ok := ns.mu.ifStates[tcpip.NICID(id)]
+ _, ok := ns.mu.ifStates[nicid]
ns.mu.Unlock()
if !ok {
return &stack.Error{Type: stack.ErrorTypeNotFound}
}
- var protocol tcpip.NetworkProtocolNumber
- switch tag := addr.IpAddress.Which(); tag {
- case net.IpAddressIpv4:
- protocol = ipv4.ProtocolNumber
- case net.IpAddressIpv6:
- protocol = ipv6.ProtocolNumber
- default:
- panic(fmt.Sprintf("unknown IpAddress type %d", tag))
- }
-
- if err := ns.removeInterfaceAddress(tcpip.NICID(id), protocol, fidlconv.ToTCPIPAddress(addr.IpAddress), uint8(addr.PrefixLen)); err != nil {
- syslog.Errorf("failed to remove interface address: %s", err)
+ if err := ns.removeInterfaceAddress(nicid, protocolAddr); err != nil {
+ syslog.Errorf("(*Netstack).delInterfaceAddr(%s) failed (NIC %d): %s", protocolAddr.AddressWithPrefix, nicid, err)
return &stack.Error{Type: stack.ErrorTypeInternal}
}
@@ -262,13 +272,7 @@
return &stack.Error{Type: stack.ErrorTypeInvalidArgs}
}
- sn, err := fidlconv.ToTCPIPSubnet(subnet)
- if err != nil {
- syslog.Errorf("cannot convert subnet %+v: %s", subnet, err)
- return &stack.Error{Type: stack.ErrorTypeInvalidArgs}
- }
-
- if err := ns.DelRoute(tcpip.Route{Destination: sn.ID(), Mask: sn.Mask()}); err != nil {
+ if err := ns.DelRoute(tcpip.Route{Destination: fidlconv.ToTCPIPSubnet(subnet)}); err != nil {
syslog.Errorf("deleting forwarding entry %+v from route table failed: %s", subnet, err)
return &stack.Error{Type: stack.ErrorTypeNotFound}
}
diff --git a/src/connectivity/network/netstack/fuchsia_net_stack_test.go b/src/connectivity/network/netstack/fuchsia_net_stack_test.go
index 91516f4..81b11ae 100644
--- a/src/connectivity/network/netstack/fuchsia_net_stack_test.go
+++ b/src/connectivity/network/netstack/fuchsia_net_stack_test.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "syscall/zx/fidl"
"testing"
"netstack/fidlconv"
@@ -48,7 +47,6 @@
}
func TestFuchsiaNetStack(t *testing.T) {
- go fidl.Serve()
t.Run("Add and Delete Forwarding Entries", func(t *testing.T) {
ns := newNetstack(t)
eth := deviceForAddEth(ethernet.Info{}, t)
diff --git a/src/connectivity/network/netstack/ifconfig/ifconfig.go b/src/connectivity/network/netstack/ifconfig/ifconfig.go
index 7b63938..78b1b24 100644
--- a/src/connectivity/network/netstack/ifconfig/ifconfig.go
+++ b/src/connectivity/network/netstack/ifconfig/ifconfig.go
@@ -150,12 +150,12 @@
func (a *netstackClientApp) newRouteFromArgs(args []string) (route netstack.RouteTableEntry2, err error) {
destination, remaining := args[0], args[1:]
- dstAddr, dstSubnet, err := net.ParseCIDR(destination)
+ _, dstSubnet, err := net.ParseCIDR(destination)
if err != nil {
return route, fmt.Errorf("invalid destination (destination must be provided in CIDR format): %s", destination)
}
- route.Destination = toIpAddress(dstAddr)
+ route.Destination = toIpAddress(dstSubnet.IP)
route.Netmask = toIpAddress(net.IP(dstSubnet.Mask))
for len(remaining) > 0 {
diff --git a/src/connectivity/network/netstack/ifconfig/ifconfig_test.go b/src/connectivity/network/netstack/ifconfig/ifconfig_test.go
index 8f5e4bd..b00ad21 100644
--- a/src/connectivity/network/netstack/ifconfig/ifconfig_test.go
+++ b/src/connectivity/network/netstack/ifconfig/ifconfig_test.go
@@ -49,7 +49,7 @@
RunQuietly(t, "/bin/ifconfig", "route", "add", "1.2.3.4/14", "gateway", "9.8.7.6", "iface", "lo")
out := Run(t, "/bin/ifconfig", "route", "show")
- expected := "1.2.3.4/14 via 9.8.7.6 lo"
+ expected := "1.0.0.0/14 via 9.8.7.6 lo"
if !strings.Contains(out, expected) {
t.Errorf("ifconfig route add failed, couldn't find '%s' in '%s'", expected, out)
}
diff --git a/src/connectivity/network/netstack/link/bridge/bridge_test.go b/src/connectivity/network/netstack/link/bridge/bridge_test.go
index b4fadcb..9b75dba 100644
--- a/src/connectivity/network/netstack/link/bridge/bridge_test.go
+++ b/src/connectivity/network/netstack/link/bridge/bridge_test.go
@@ -7,6 +7,7 @@
"time"
"netstack/link/bridge"
+ "netstack/util"
"github.com/google/netstack/tcpip"
"github.com/google/netstack/tcpip/buffer"
@@ -64,12 +65,14 @@
ep1, ep2 := pipe(tcpip.LinkAddress(bytes.Repeat([]byte{1}, header.EthernetAddressSize)), tcpip.LinkAddress(bytes.Repeat([]byte{2}, header.EthernetAddressSize)))
ep3, ep4 := pipe(tcpip.LinkAddress(bytes.Repeat([]byte{3}, header.EthernetAddressSize)), tcpip.LinkAddress(bytes.Repeat([]byte{4}, header.EthernetAddressSize)))
s1addr := tcpip.Address([]byte{1, 1, 1, 1})
+ s1subnet := util.PointSubnet(s1addr)
s1, err := makeStackWithEndpoint(ep1, s1addr)
if err != nil {
t.Fatal(err)
}
baddr := tcpip.Address([]byte{2, 2, 2, 2})
+ bsubnet := util.PointSubnet(baddr)
sb, b, err := makeStackWithBridgedEndpoints(ep2, ep3, baddr)
if err != nil {
t.Fatal(err)
@@ -80,6 +83,7 @@
}
s2addr := tcpip.Address([]byte{3, 3, 3, 3})
+ s2subnet := util.PointSubnet(s2addr)
s2, err := makeStackWithEndpoint(ep4, s2addr)
if err != nil {
t.Fatal(err)
@@ -89,6 +93,7 @@
// to the address on the virtual NIC representing the bridge itself), to test
// that constituent links are still routable.
bcaddr := tcpip.Address([]byte{4, 4, 4, 4})
+ bcsubnet := util.PointSubnet(bcaddr)
if err := sb.AddAddress(1, header.ARPProtocolNumber, arp.ProtocolAddress); err != nil {
t.Fatal(fmt.Errorf("AddAddress failed: %s", err))
}
@@ -98,26 +103,22 @@
s1.SetRouteTable([]tcpip.Route{
{
- Destination: s2addr,
- Mask: "\xff\xff\xff\xff",
+ Destination: s2subnet,
NIC: 1,
},
{
- Destination: baddr,
- Mask: "\xff\xff\xff\xff",
+ Destination: bsubnet,
NIC: 1,
},
{
- Destination: bcaddr,
- Mask: "\xff\xff\xff\xff",
+ Destination: bcsubnet,
NIC: 1,
},
})
sb.SetRouteTable([]tcpip.Route{
{
- Destination: s1addr,
- Mask: "\xff\xff\xff\xff",
+ Destination: s1subnet,
NIC: 1,
},
})
@@ -125,8 +126,7 @@
s2.SetRouteTable(
[]tcpip.Route{
{
- Destination: s1addr,
- Mask: "\xff\xff\xff\xff",
+ Destination: s1subnet,
NIC: 2,
},
},
diff --git a/src/connectivity/network/netstack/netstack.go b/src/connectivity/network/netstack/netstack.go
index 27a75bc..50d7a15 100644
--- a/src/connectivity/network/netstack/netstack.go
+++ b/src/connectivity/network/netstack/netstack.go
@@ -7,7 +7,8 @@
import (
"context"
"fmt"
- "strings"
+ "net"
+ "netstack/util"
"sync"
"sync/atomic"
"syscall/zx"
@@ -17,17 +18,14 @@
"netstack/dhcp"
"netstack/dns"
- "netstack/fidlconv"
"netstack/filter"
"netstack/link"
"netstack/link/bridge"
"netstack/link/eth"
"netstack/routes"
- "netstack/util"
"fidl/fuchsia/device"
"fidl/fuchsia/hardware/ethernet"
- "fidl/fuchsia/net"
"fidl/fuchsia/netstack"
"github.com/google/netstack/tcpip"
@@ -127,23 +125,26 @@
func defaultRoutes(nicid tcpip.NICID, gateway tcpip.Address) []tcpip.Route {
return []tcpip.Route{
{
- Destination: tcpip.Address(strings.Repeat("\x00", 4)),
- Mask: tcpip.AddressMask(strings.Repeat("\x00", 4)),
+ Destination: header.IPv4EmptySubnet,
Gateway: gateway,
NIC: nicid,
},
{
- Destination: tcpip.Address(strings.Repeat("\x00", 16)),
- Mask: tcpip.AddressMask(strings.Repeat("\x00", 16)),
+ Destination: header.IPv6EmptySubnet,
NIC: nicid,
},
}
}
-func subnetRoute(addr tcpip.Address, mask tcpip.AddressMask, nicid tcpip.NICID) tcpip.Route {
+func addressWithPrefixRoute(nicid tcpip.NICID, addr tcpip.AddressWithPrefix) tcpip.Route {
+ mask := net.CIDRMask(addr.PrefixLen, len(addr.Address)*8)
+ destination, err := tcpip.NewSubnet(tcpip.Address(net.IP(addr.Address).Mask(mask)), tcpip.AddressMask(mask))
+ if err != nil {
+ panic(err)
+ }
+
return tcpip.Route{
- Destination: util.ApplyMask(addr, mask),
- Mask: mask,
+ Destination: destination,
NIC: nicid,
}
}
@@ -179,7 +180,7 @@
}
for _, r := range rs {
- switch len(r.Destination) {
+ switch len(r.Destination.ID()) {
case header.IPv4AddressSize, header.IPv6AddressSize:
default:
// TODO(NET-2244): update this to return an error; panicing here enables syzkaller to find
@@ -264,28 +265,24 @@
return nil
}
-func (ns *Netstack) removeInterfaceAddress(nic tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address, prefixLen uint8) error {
- subnet, err := toSubnet(addr, prefixLen)
- if err != nil {
- return fmt.Errorf("error parsing subnet format for NIC ID %d: %s", nic, err)
- }
- route := subnetRoute(addr, subnet.Mask(), nic)
- syslog.Infof("removing static IP %s/%d from NIC %d, deleting subnet route %+v", addr, prefixLen, nic, route)
+func (ns *Netstack) removeInterfaceAddress(nic tcpip.NICID, addr tcpip.ProtocolAddress) error {
+ route := addressWithPrefixRoute(nic, addr.AddressWithPrefix)
+ syslog.Infof("removing static IP %s from NIC %d, deleting subnet route %+v", addr.AddressWithPrefix, nic, route)
ns.mu.Lock()
if err := func() error {
- if _, found := ns.findAddress(nic, protocol, addr); !found {
- return fmt.Errorf("address %s doesn't exist on NIC ID %d", addr, nic)
+ if _, found := ns.findAddress(nic, addr); !found {
+ return fmt.Errorf("address %s doesn't exist on NIC ID %d", addr.AddressWithPrefix, nic)
}
if err := ns.DelRouteLocked(route); err != nil {
// The route might have been removed by user action. Continue.
}
- if err := ns.mu.stack.RemoveAddress(nic, addr); err == tcpip.ErrUnknownNICID {
+ if err := ns.mu.stack.RemoveAddress(nic, addr.AddressWithPrefix.Address); err == tcpip.ErrUnknownNICID {
panic(fmt.Sprintf("stack.RemoveAddress(_): NIC [%d] not found", nic))
} else if err != nil {
- return fmt.Errorf("error removing address %s from NIC ID %d: %s", addr, nic, err)
+ return fmt.Errorf("error removing address %s from NIC ID %d: %s", addr.AddressWithPrefix, nic, err)
}
return nil
@@ -300,43 +297,25 @@
return nil
}
-func toSubnet(address tcpip.Address, prefixLen uint8) (tcpip.Subnet, error) {
- m := util.CIDRMask(int(prefixLen), int(len(address)*8))
- if len(m) == 0 {
- return tcpip.Subnet{}, fmt.Errorf("net.CIDRMask(%d, %d) = nil", prefixLen, len(address)*8)
- }
- return tcpip.NewSubnet(util.ApplyMask(address, m), m)
-}
-
-func (ns *Netstack) addInterfaceAddress(nic tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address, prefixLen uint8) error {
- subnet, err := toSubnet(addr, prefixLen)
- if err != nil {
- return fmt.Errorf("error parsing subnet format for NIC ID %d: %s", nic, err)
- }
- route := subnetRoute(addr, subnet.Mask(), nic)
- syslog.Infof("adding static IP %v/%d to NIC %d, creating subnet route %+v with metric=<not-set>, dynamic=false", addr, prefixLen, nic, route)
+func (ns *Netstack) addInterfaceAddress(nic tcpip.NICID, addr tcpip.ProtocolAddress) error {
+ route := addressWithPrefixRoute(nic, addr.AddressWithPrefix)
+ syslog.Infof("adding static IP %s to NIC %d, creating subnet route %+v with metric=<not-set>, dynamic=false", addr.AddressWithPrefix, nic, route)
ns.mu.Lock()
if err := func() error {
- if a, found := ns.findAddress(nic, protocol, addr); found {
- if int(prefixLen) == a.AddressWithPrefix.PrefixLen {
- return fmt.Errorf("address %s/%d already exists on NIC ID %d", addr, prefixLen, nic)
+ if a, found := ns.findAddress(nic, addr); found {
+ if a.AddressWithPrefix.PrefixLen == addr.AddressWithPrefix.PrefixLen {
+ return fmt.Errorf("address %s already exists on NIC ID %d", addr.AddressWithPrefix, nic)
}
// Same address but different prefix. Remove the address and re-add it
// with the new prefix (below).
- if err := ns.mu.stack.RemoveAddress(nic, addr); err != nil {
- return fmt.Errorf("NIC %d: failed to remove address %s: %s", nic, addr, err)
+ if err := ns.mu.stack.RemoveAddress(nic, addr.AddressWithPrefix.Address); err != nil {
+ return fmt.Errorf("NIC %d: failed to remove address %s: %s", nic, addr.AddressWithPrefix, err)
}
}
- if err := ns.mu.stack.AddProtocolAddress(nic, tcpip.ProtocolAddress{
- Protocol: protocol,
- AddressWithPrefix: tcpip.AddressWithPrefix{
- Address: addr,
- PrefixLen: int(prefixLen),
- },
- }); err != nil {
- return fmt.Errorf("error adding address %s/%d to NIC ID %d: %s", addr, prefixLen, nic, err)
+ if err := ns.mu.stack.AddProtocolAddress(nic, addr); err != nil {
+ return fmt.Errorf("error adding address %s to NIC ID %d: %s", addr.AddressWithPrefix, nic, err)
}
if err := ns.AddRouteLocked(route, metricNotSet, false); err != nil {
@@ -390,7 +369,7 @@
// Add a default route and a route for the local subnet.
rs := defaultRoutes(ifs.nicid, config.Gateway)
- rs = append(rs, subnetRoute(newAddr.Address, config.SubnetMask, ifs.nicid))
+ rs = append(rs, addressWithPrefixRoute(ifs.nicid, newAddr))
syslog.Infof("adding routes %+v with metric=<not-set> dynamic=true", rs)
if err := ifs.ns.AddRoutesLocked(rs, metricNotSet, true /* dynamic */); err != nil {
@@ -599,13 +578,11 @@
if err := ns.AddRoutesLocked(
[]tcpip.Route{
{
- Destination: ipv4Loopback,
- Mask: tcpip.AddressMask(strings.Repeat("\xff", 4)),
+ Destination: util.PointSubnet(ipv4Loopback),
NIC: nicid,
},
{
- Destination: ipv6Loopback,
- Mask: tcpip.AddressMask(strings.Repeat("\xff", 16)),
+ Destination: util.PointSubnet(ipv6Loopback),
NIC: nicid,
},
},
@@ -735,24 +712,6 @@
return ifs, nil
}
-func (ns *Netstack) validateInterfaceAddress(address net.IpAddress, prefixLen uint8) (tcpip.NetworkProtocolNumber, tcpip.Address, netstack.NetErr) {
- var protocol tcpip.NetworkProtocolNumber
- switch address.Which() {
- case net.IpAddressIpv4:
- protocol = ipv4.ProtocolNumber
- case net.IpAddressIpv6:
- return 0, "", netstack.NetErr{Status: netstack.StatusIpv4Only, Message: "IPv6 not yet supported"}
- }
-
- addr := fidlconv.ToTCPIPAddress(address)
-
- if (8 * len(addr)) < int(prefixLen) {
- return 0, "", netstack.NetErr{Status: netstack.StatusParseError, Message: "prefix length exceeds address length"}
- }
-
- return protocol, addr, netstack.NetErr{Status: netstack.StatusOk}
-}
-
func (ns *Netstack) getAddressesLocked(nic tcpip.NICID) []tcpip.ProtocolAddress {
nicInfo := ns.mu.stack.NICInfo()
info, ok := nicInfo[nic]
@@ -764,10 +723,12 @@
// findAddress finds the given address in the addresses currently assigned to
// the NIC. Note that no duplicate addresses exist on a NIC.
-func (ns *Netstack) findAddress(nic tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address) (tcpip.ProtocolAddress, bool) {
- addresses := ns.getAddressesLocked(nic)
- for _, a := range addresses {
- if a.Protocol == protocol && a.AddressWithPrefix.Address == addr {
+func (ns *Netstack) findAddress(nic tcpip.NICID, addr tcpip.ProtocolAddress) (tcpip.ProtocolAddress, bool) {
+ // Ignore prefix length.
+ addr.AddressWithPrefix.PrefixLen = 0
+ for _, a := range ns.getAddressesLocked(nic) {
+ a.AddressWithPrefix.PrefixLen = 0
+ if a == addr {
return a, true
}
}
diff --git a/src/connectivity/network/netstack/netstack_service.go b/src/connectivity/network/netstack/netstack_service.go
index eefa754..e3ddd5cb 100644
--- a/src/connectivity/network/netstack/netstack_service.go
+++ b/src/connectivity/network/netstack/netstack_service.go
@@ -5,9 +5,10 @@
package netstack
import (
+ "fidl/fuchsia/net/stack"
"fmt"
+ "net"
"sort"
- "strings"
"syscall/zx"
"syscall/zx/fidl"
"syscall/zx/zxwait"
@@ -17,11 +18,10 @@
"netstack/fidlconv"
"netstack/link"
"netstack/routes"
- "netstack/util"
"fidl/fuchsia/hardware/ethernet"
"fidl/fuchsia/io"
- "fidl/fuchsia/net"
+ fidlnet "fidl/fuchsia/net"
"fidl/fuchsia/netstack"
"github.com/google/netstack/tcpip"
@@ -86,18 +86,18 @@
return netstack.NetInterface2{}, fmt.Errorf("stack.GetMainNICAddress(_): %s", err)
}
- mask := util.CIDRMask(addrWithPrefix.PrefixLen, len(addrWithPrefix.Address)*8)
+ mask := net.CIDRMask(addrWithPrefix.PrefixLen, len(addrWithPrefix.Address)*8)
broadaddr := []byte(addrWithPrefix.Address)
for i := range broadaddr {
broadaddr[i] |= ^mask[i]
}
addresses := ifs.ns.getAddressesLocked(ifs.nicid)
- ipv6addrs := make([]net.Subnet, 0, len(addresses))
+ ipv6addrs := make([]fidlnet.Subnet, 0, len(addresses))
for _, address := range addresses {
if address.Protocol == ipv6.ProtocolNumber {
- ipv6addrs = append(ipv6addrs, net.Subnet{
+ ipv6addrs = append(ipv6addrs, fidlnet.Subnet{
Addr: fidlconv.ToNetIpAddress(address.AddressWithPrefix.Address),
PrefixLen: uint8(address.AddressWithPrefix.PrefixLen),
})
@@ -202,7 +202,7 @@
rt2 := nsToRouteTable2(ni.ns.GetExtendedRouteTable())
rt := make([]netstack.RouteTableEntry, 0, len(rt2))
for _, r2 := range rt2 {
- var gateway net.IpAddress
+ var gateway fidlnet.IpAddress
if r2.Gateway != nil {
gateway = *r2.Gateway
} else {
@@ -218,33 +218,17 @@
return rt, nil
}
-func nsToRouteTable2(table []routes.ExtendedRoute) (out []netstack.RouteTableEntry2) {
+func nsToRouteTable2(table []routes.ExtendedRoute) []netstack.RouteTableEntry2 {
+ out := make([]netstack.RouteTableEntry2, 0, len(table))
for _, e := range table {
- // Ensure that if any of the returned addresses are "empty",
- // they still have the appropriate length.
- l := 0
- if len(e.Route.Destination) > 0 {
- l = len(e.Route.Destination)
- } else if len(e.Route.Mask) > 0 {
- l = len(e.Route.Destination)
- }
- dest := e.Route.Destination
- mask := e.Route.Mask
- if len(dest) == 0 {
- dest = tcpip.Address(strings.Repeat("\x00", l))
- }
- if len(mask) == 0 {
- mask = tcpip.AddressMask(strings.Repeat("\x00", l))
- }
-
- var gatewayPtr *net.IpAddress
+ var gatewayPtr *fidlnet.IpAddress
if len(e.Route.Gateway) != 0 {
gateway := fidlconv.ToNetIpAddress(e.Route.Gateway)
gatewayPtr = &gateway
}
out = append(out, netstack.RouteTableEntry2{
- Destination: fidlconv.ToNetIpAddress(dest),
- Netmask: fidlconv.ToNetIpAddress(tcpip.Address(mask)),
+ Destination: fidlconv.ToNetIpAddress(e.Route.Destination.ID()),
+ Netmask: fidlconv.ToNetIpAddress(tcpip.Address(e.Route.Destination.Mask())),
Gateway: gatewayPtr,
Nicid: uint32(e.Route.NIC),
Metric: uint32(e.Metric),
@@ -254,16 +238,18 @@
}
func routeToNs(r netstack.RouteTableEntry2) tcpip.Route {
- var gateway tcpip.Address
- if r.Gateway != nil {
- gateway = fidlconv.ToTCPIPAddress(*r.Gateway)
+ prefixLen, _ := net.IPMask(fidlconv.ToTCPIPAddress(r.Netmask)).Size()
+ route := tcpip.Route{
+ Destination: fidlconv.ToTCPIPSubnet(fidlnet.Subnet{
+ Addr: r.Destination,
+ PrefixLen: uint8(prefixLen),
+ }),
+ NIC: tcpip.NICID(r.Nicid),
}
- return tcpip.Route{
- Destination: fidlconv.ToTCPIPAddress(r.Destination),
- Mask: tcpip.AddressMask(fidlconv.ToTCPIPAddress(r.Netmask)),
- Gateway: gateway,
- NIC: tcpip.NICID(r.Nicid),
+ if g := r.Gateway; g != nil {
+ route.Gateway = fidlconv.ToTCPIPAddress(*g)
}
+ return route
}
type routeTableTransactionImpl struct {
@@ -322,32 +308,33 @@
}
// Add address to the given network interface.
-func (ni *netstackImpl) SetInterfaceAddress(nicid uint32, address net.IpAddress, prefixLen uint8) (netstack.NetErr, error) {
- nic := tcpip.NICID(nicid)
- protocol, addr, neterr := ni.ns.validateInterfaceAddress(address, prefixLen)
- if neterr.Status != netstack.StatusOk {
- return neterr, nil
+func (ni *netstackImpl) SetInterfaceAddress(nicid uint32, address fidlnet.IpAddress, prefixLen uint8) (netstack.NetErr, error) {
+ protocolAddr := toProtocolAddr(stack.InterfaceAddress{
+ IpAddress: address,
+ PrefixLen: prefixLen,
+ })
+ if protocolAddr.AddressWithPrefix.PrefixLen > 8*len(protocolAddr.AddressWithPrefix.Address) {
+ return netstack.NetErr{Status: netstack.StatusParseError, Message: "prefix length exceeds address length"}, nil
}
-
- if err := ni.ns.addInterfaceAddress(nic, protocol, addr, prefixLen); err != nil {
+ if err := ni.ns.addInterfaceAddress(tcpip.NICID(nicid), protocolAddr); err != nil {
return netstack.NetErr{Status: netstack.StatusUnknownError, Message: err.Error()}, nil
}
- return netstack.NetErr{Status: netstack.StatusOk, Message: ""}, nil
+ return netstack.NetErr{Status: netstack.StatusOk}, nil
}
-func (ni *netstackImpl) RemoveInterfaceAddress(nicid uint32, address net.IpAddress, prefixLen uint8) (netstack.NetErr, error) {
- nic := tcpip.NICID(nicid)
- protocol, addr, neterr := ni.ns.validateInterfaceAddress(address, prefixLen)
-
- if neterr.Status != netstack.StatusOk {
- return neterr, nil
+func (ni *netstackImpl) RemoveInterfaceAddress(nicid uint32, address fidlnet.IpAddress, prefixLen uint8) (netstack.NetErr, error) {
+ protocolAddr := toProtocolAddr(stack.InterfaceAddress{
+ IpAddress: address,
+ PrefixLen: prefixLen,
+ })
+ if protocolAddr.AddressWithPrefix.PrefixLen > 8*len(protocolAddr.AddressWithPrefix.Address) {
+ return netstack.NetErr{Status: netstack.StatusParseError, Message: "prefix length exceeds address length"}, nil
}
-
- if err := ni.ns.removeInterfaceAddress(nic, protocol, addr, prefixLen); err != nil {
+ if err := ni.ns.removeInterfaceAddress(tcpip.NICID(nicid), protocolAddr); err != nil {
return netstack.NetErr{Status: netstack.StatusUnknownError, Message: err.Error()}, nil
}
- return netstack.NetErr{Status: netstack.StatusOk, Message: ""}, nil
+ return netstack.NetErr{Status: netstack.StatusOk}, nil
}
// SetInterfaceMetric updates the metric of an interface.
@@ -449,7 +436,7 @@
ns *Netstack
}
-func (dns *dnsImpl) SetNameServers(servers []net.IpAddress) error {
+func (dns *dnsImpl) SetNameServers(servers []fidlnet.IpAddress) error {
ss := make([]tcpip.Address, len(servers))
for i, s := range servers {
diff --git a/src/connectivity/network/netstack/netstack_service_impl_test.go b/src/connectivity/network/netstack/netstack_service_impl_test.go
index c4aa331..0a5c821 100644
--- a/src/connectivity/network/netstack/netstack_service_impl_test.go
+++ b/src/connectivity/network/netstack/netstack_service_impl_test.go
@@ -70,7 +70,7 @@
t.Errorf("can't start a transaction")
}
- destinationAddress, destinationSubnet, err := net.ParseCIDR("1.2.3.4/24")
+ _, destinationSubnet, err := net.ParseCIDR("1.2.3.4/24")
AssertNoError(t, err)
gatewayAddress := net.ParseIP("5.6.7.8")
if gatewayAddress == nil {
@@ -78,7 +78,7 @@
}
gateway := toIpAddress(gatewayAddress)
newRouteTableEntry2 := netstack.RouteTableEntry2{
- Destination: toIpAddress(destinationAddress),
+ Destination: toIpAddress(destinationSubnet.IP),
Netmask: toIpAddress(net.IP(destinationSubnet.Mask)),
Gateway: &gateway,
Nicid: uint32(ifs.nicid),
diff --git a/src/connectivity/network/netstack/netstack_test.go b/src/connectivity/network/netstack/netstack_test.go
index e2494e8..61362b9 100644
--- a/src/connectivity/network/netstack/netstack_test.go
+++ b/src/connectivity/network/netstack/netstack_test.go
@@ -5,14 +5,14 @@
package netstack
import (
+ "net"
"sort"
- "strings"
"syscall/zx"
"testing"
"time"
"fidl/fuchsia/hardware/ethernet"
- "fidl/fuchsia/net"
+ fidlnet "fidl/fuchsia/net"
"fidl/fuchsia/net/stack"
"fidl/fuchsia/netstack"
ethernetext "fidlext/fuchsia/hardware/ethernet"
@@ -27,7 +27,6 @@
"github.com/google/go-cmp/cmp"
"github.com/google/netstack/tcpip"
- "github.com/google/netstack/tcpip/header"
"github.com/google/netstack/tcpip/network/arp"
"github.com/google/netstack/tcpip/network/ipv4"
"github.com/google/netstack/tcpip/network/ipv6"
@@ -372,8 +371,8 @@
t.Fatalf("got len(GetInterfaces2()) = %d, want != %d", l, l)
}
- var expectedAddr net.IpAddress
- expectedAddr.SetIpv4(net.Ipv4Address{})
+ var expectedAddr fidlnet.IpAddress
+ expectedAddr.SetIpv4(fidlnet.Ipv4Address{})
for _, iface := range interfaces {
if iface.Addr != expectedAddr {
t.Errorf("got interface %+v, want Addr = %+v", iface, expectedAddr)
@@ -504,15 +503,21 @@
func TestAddRouteParameterValidation(t *testing.T) {
ns := newNetstack(t)
d := deviceForAddEth(ethernet.Info{}, t)
- interfaceAddress, prefix := tcpip.Address("\xf0\xf0\xf0\xf0"), uint8(24)
+ addr := tcpip.ProtocolAddress{
+ Protocol: ipv4.ProtocolNumber,
+ AddressWithPrefix: tcpip.AddressWithPrefix{
+ Address: tcpip.Address("\xf0\xf0\xf0\xf0"),
+ PrefixLen: 24,
+ },
+ }
subnetLocalAddress := tcpip.Address("\xf0\xf0\xf0\xf1")
ifState, err := ns.addEth(testTopoPath, netstack.InterfaceConfig{}, &d)
if err != nil {
t.Fatalf("got ns.addEth(_) = _, %s want = _, nil", err)
}
- if err := ns.addInterfaceAddress(ifState.nicid, ipv4.ProtocolNumber, interfaceAddress, prefix); err != nil {
- t.Fatalf("ns.addInterfaceAddress(%d, %d, %s, %d) = %s", ifState.nicid, ipv4.ProtocolNumber, interfaceAddress, prefix, err)
+ if err := ns.addInterfaceAddress(ifState.nicid, addr); err != nil {
+ t.Fatalf("ns.addInterfaceAddress(%d, %s) = %s", ifState.nicid, addr.AddressWithPrefix, err)
}
tests := []struct {
@@ -527,10 +532,15 @@
// TODO(NET-2244): don't panic when given invalid route destinations
name: "zero-length destination",
route: tcpip.Route{
- Destination: tcpip.Address(""),
- Mask: tcpip.AddressMask(header.IPv4Broadcast),
- Gateway: testV4Address,
- NIC: ifState.nicid,
+ Destination: func() tcpip.Subnet {
+ subnet, err := tcpip.NewSubnet("", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ return subnet
+ }(),
+ Gateway: testV4Address,
+ NIC: ifState.nicid,
},
metric: routes.Metric(0),
shouldPanic: true,
@@ -539,10 +549,15 @@
// TODO(NET-2244): don't panic when given invalid route destinations
name: "invalid destination",
route: tcpip.Route{
- Destination: tcpip.Address("\xff"),
- Mask: tcpip.AddressMask(header.IPv4Broadcast),
- Gateway: testV4Address,
- NIC: ifState.nicid,
+ Destination: func() tcpip.Subnet {
+ subnet, err := tcpip.NewSubnet("\xff", "\xff")
+ if err != nil {
+ t.Fatal(err)
+ }
+ return subnet
+ }(),
+ Gateway: testV4Address,
+ NIC: ifState.nicid,
},
metric: routes.Metric(0),
shouldPanic: true,
@@ -550,8 +565,7 @@
{
name: "IPv4 destination no NIC invalid gateway",
route: tcpip.Route{
- Destination: testV4Address,
- Mask: tcpip.AddressMask(header.IPv4Broadcast),
+ Destination: util.PointSubnet(testV4Address),
Gateway: testV4Address,
NIC: 0,
},
@@ -561,8 +575,7 @@
{
name: "IPv6 destination no NIC invalid gateway",
route: tcpip.Route{
- Destination: testV6Address,
- Mask: tcpip.AddressMask(strings.Repeat("\xff", 16)),
+ Destination: util.PointSubnet(testV6Address),
Gateway: testV6Address,
NIC: 0,
},
@@ -572,8 +585,7 @@
{
name: "IPv4 destination no NIC valid gateway",
route: tcpip.Route{
- Destination: testV4Address,
- Mask: tcpip.AddressMask(header.IPv4Broadcast),
+ Destination: util.PointSubnet(testV4Address),
Gateway: subnetLocalAddress,
NIC: 0,
},
@@ -581,9 +593,7 @@
{
name: "zero length gateway",
route: tcpip.Route{
- Destination: testV4Address,
- Mask: tcpip.AddressMask(header.IPv4Broadcast),
- Gateway: tcpip.Address(""),
+ Destination: util.PointSubnet(testV4Address),
NIC: ifState.nicid,
},
},
@@ -622,6 +632,22 @@
gatewayAddress[len(gatewayAddress)-1]++
const defaultLeaseLength = 60 * time.Second
+ defaultMask := net.IP(testV4Address).DefaultMask()
+ prefixLen, _ := defaultMask.Size()
+
+ destination1, err := tcpip.NewSubnet(util.Parse("192.168.42.0"), tcpip.AddressMask(util.Parse("255.255.255.0")))
+ if err != nil {
+ t.Fatal(err)
+ }
+ destination2, err := tcpip.NewSubnet(util.Parse("0.0.0.0"), tcpip.AddressMask(util.Parse("0.0.0.0")))
+ if err != nil {
+ t.Fatal(err)
+ }
+ destination3, err := tcpip.NewSubnet(util.Parse("::"), tcpip.AddressMask(util.Parse("::")))
+ if err != nil {
+ t.Fatal(err)
+ }
+
tests := []struct {
name string
oldAddr, newAddr tcpip.AddressWithPrefix
@@ -633,20 +659,19 @@
oldAddr: tcpip.AddressWithPrefix{},
newAddr: tcpip.AddressWithPrefix{
Address: testV4Address,
- PrefixLen: util.PrefixLength(util.DefaultMask(testV4Address)),
+ PrefixLen: prefixLen,
},
config: dhcp.Config{
ServerAddress: tcpip.Address(serverAddress),
Gateway: tcpip.Address(serverAddress),
- SubnetMask: util.DefaultMask(testV4Address),
+ SubnetMask: tcpip.AddressMask(defaultMask),
DNS: []tcpip.Address{tcpip.Address(gatewayAddress)},
LeaseLength: defaultLeaseLength,
},
expectedRouteTable: []routes.ExtendedRoute{
{
Route: tcpip.Route{
- Destination: util.Parse("192.168.42.0"),
- Mask: tcpip.AddressMask(util.Parse("255.255.255.0")),
+ Destination: destination1,
NIC: 1,
},
Metric: 0,
@@ -656,8 +681,7 @@
},
{
Route: tcpip.Route{
- Destination: util.Parse("0.0.0.0"),
- Mask: tcpip.AddressMask(util.Parse("0.0.0.0")),
+ Destination: destination2,
Gateway: util.Parse("192.168.42.18"),
NIC: 1,
},
@@ -668,8 +692,7 @@
},
{
Route: tcpip.Route{
- Destination: util.Parse("::"),
- Mask: tcpip.AddressMask(util.Parse("::")),
+ Destination: destination3,
NIC: 1,
},
Metric: 0,
@@ -694,7 +717,7 @@
t.Errorf("ifState.mu.dnsServers mismatch (-want +got):\n%s", diff)
}
- if diff := cmp.Diff(ifState.ns.GetExtendedRouteTable(), test.expectedRouteTable); diff != "" {
+ if diff := cmp.Diff(ifState.ns.GetExtendedRouteTable(), test.expectedRouteTable, cmp.AllowUnexported(tcpip.Subnet{})); diff != "" {
t.Errorf("GetExtendedRouteTable() mismatch (-want +got):\n%s", diff)
}
@@ -751,10 +774,6 @@
}
}
-func getNetmask(prefix uint8, bits int) net.IpAddress {
- return fidlconv.ToNetIpAddress(tcpip.Address(util.CIDRMask(int(prefix), bits)))
-}
-
// Returns an ethernetext.Device struct that implements
// ethernet.Device and can be started and stopped.
//
diff --git a/src/connectivity/network/netstack/routes/routes.go b/src/connectivity/network/netstack/routes/routes.go
index 9035728..b302131 100644
--- a/src/connectivity/network/netstack/routes/routes.go
+++ b/src/connectivity/network/netstack/routes/routes.go
@@ -64,32 +64,12 @@
// Match matches the given address against this route.
func (er *ExtendedRoute) Match(addr tcpip.Address) bool {
- r := er.Route
- if len(addr) != len(r.Destination) {
- return false
- }
- for i := 0; i < len(r.Destination); i++ {
- if (addr[i] & r.Mask[i]) != r.Destination[i] {
- return false
- }
- }
- return true
-}
-
-// Temporary stringer helper until tcpip.Route implements one.
-func RouteStringer(r *tcpip.Route) string {
- var out strings.Builder
- fmt.Fprintf(&out, "%s/%d", r.Destination, util.PrefixLength(r.Mask))
- if len(r.Gateway) > 0 {
- fmt.Fprintf(&out, " via %s", r.Gateway)
- }
- fmt.Fprintf(&out, " nic %d", r.NIC)
- return out.String()
+ return er.Route.Destination.Contains(addr)
}
func (er *ExtendedRoute) String() string {
var out strings.Builder
- fmt.Fprintf(&out, "%s", RouteStringer(&er.Route))
+ fmt.Fprintf(&out, "%s", er.Route)
if er.MetricTracksInterface {
fmt.Fprintf(&out, " metric[if] %d", er.Metric)
} else {
@@ -125,18 +105,12 @@
}
}
-func (rt *RouteTable) String() string {
- rt.mu.Lock()
- defer rt.mu.Unlock()
- return rt.mu.routes.String()
-}
-
// For debugging.
-func (rt *RouteTable) Dump() {
+func (rt *RouteTable) dumpLocked() {
if rt == nil {
syslog.VLogTf(syslog.TraceVerbosity, tag, "Current Route Table:<nil>")
} else {
- syslog.VLogTf(syslog.TraceVerbosity, tag, "Current Route Table:\n%s", rt)
+ syslog.VLogTf(syslog.TraceVerbosity, tag, "Current Route Table:\n%s", rt.mu.routes)
}
}
@@ -151,14 +125,14 @@
// route already exists, it simply updates that route's metric, dynamic and
// enabled fields.
func (rt *RouteTable) AddRoute(route tcpip.Route, metric Metric, tracksInterface bool, dynamic bool, enabled bool) {
- syslog.VLogTf(syslog.DebugVerbosity, tag, "RouteTable:Adding route %s with metric:%d, trackIf=%t, dynamic=%t, enabled=%t", RouteStringer(&route), metric, tracksInterface, dynamic, enabled)
+ syslog.VLogTf(syslog.DebugVerbosity, tag, "RouteTable:Adding route %s with metric:%d, trackIf=%t, dynamic=%t, enabled=%t", route, metric, tracksInterface, dynamic, enabled)
rt.mu.Lock()
defer rt.mu.Unlock()
// First check if the route already exists, and remove it.
for i, er := range rt.mu.routes {
- if IsSameRoute(route, er.Route) {
+ if er.Route == route {
rt.mu.routes = append(rt.mu.routes[:i], rt.mu.routes[i+1:]...)
break
}
@@ -189,12 +163,12 @@
rt.mu.routes[targetIdx] = newEr
}
- rt.Dump()
+ rt.dumpLocked()
}
// DelRoute removes the given route from the route table.
func (rt *RouteTable) DelRoute(route tcpip.Route) error {
- syslog.VLogTf(syslog.DebugVerbosity, tag, "RouteTable:Deleting route %s", RouteStringer(&route))
+ syslog.VLogTf(syslog.DebugVerbosity, tag, "RouteTable:Deleting route %s", route)
rt.mu.Lock()
defer rt.mu.Unlock()
@@ -204,7 +178,7 @@
rt.mu.routes = oldTable[:0]
for _, er := range oldTable {
// Match all fields that are non-zero.
- if isSameSubnet(er.Route, route) {
+ if er.Route.Destination == route.Destination {
if route.NIC == 0 || route.NIC == er.Route.NIC {
if len(route.Gateway) == 0 || route.Gateway == er.Route.Gateway {
routeDeleted = true
@@ -220,7 +194,7 @@
return fmt.Errorf("no such route")
}
- rt.Dump()
+ rt.dumpLocked()
return nil
}
@@ -229,7 +203,7 @@
rt.mu.Lock()
defer rt.mu.Unlock()
- rt.Dump()
+ rt.dumpLocked()
return append([]ExtendedRoute(nil), rt.mu.routes...)
}
@@ -269,7 +243,7 @@
rt.sortRouteTableLocked()
- rt.Dump()
+ rt.dumpLocked()
}
// UpdateRoutesByInterface applies an action to the routes pointing to an interface.
@@ -306,7 +280,7 @@
rt.sortRouteTableLocked()
- rt.Dump()
+ rt.dumpLocked()
}
// FindNIC returns the NIC-ID that the given address is routed on. This requires
@@ -317,7 +291,7 @@
for _, er := range rt.mu.routes {
// Ignore default routes.
- if util.IsAny(er.Route.Destination) {
+ if util.IsAny(er.Route.Destination.ID()) {
continue
}
if er.Match(addr) && er.Route.NIC > 0 {
@@ -337,20 +311,20 @@
// route table.
func Less(ei, ej *ExtendedRoute) bool {
ri, rj := ei.Route, ej.Route
+ riDest, rjDest := ri.Destination.ID(), rj.Destination.ID()
// Non-default before default one.
- if util.IsAny(ri.Destination) != util.IsAny(rj.Destination) {
- return !util.IsAny(ri.Destination)
+ if riAny, rjAny := util.IsAny(riDest), util.IsAny(rjDest); riAny != rjAny {
+ return !riAny
}
// IPv4 before IPv6 (arbitrary choice).
- if len(ri.Destination) != len(rj.Destination) {
- return len(ri.Destination) == header.IPv4AddressSize
+ if riLen, rjLen := len(riDest), len(rjDest); riLen != rjLen {
+ return riLen == header.IPv4AddressSize
}
// Longer prefix wins.
- li, lj := util.PrefixLength(ri.Mask), util.PrefixLength(rj.Mask)
- if len(ri.Mask) == len(rj.Mask) && li != lj {
- return li > lj
+ if riPrefix, rjPrefix := ri.Destination.Prefix(), rj.Destination.Prefix(); riPrefix != rjPrefix {
+ return riPrefix > rjPrefix
}
// Lower metrics wins.
@@ -361,7 +335,6 @@
// Everything that matters is the same. At this point we still need a
// deterministic way to tie-break. First go by destination IPs (lower wins),
// finally use the NIC.
- riDest, rjDest := []byte(ri.Destination), []byte(rj.Destination)
for i := 0; i < len(riDest); i++ {
if riDest[i] != rjDest[i] {
return riDest[i] < rjDest[i]
@@ -372,22 +345,3 @@
// tie-breaker.
return ri.NIC < rj.NIC
}
-
-func isSameSubnet(a, b tcpip.Route) bool {
- return a.Destination == b.Destination && a.Mask == b.Mask
-}
-
-// IsSameRoute returns true if two routes are the same.
-func IsSameRoute(a, b tcpip.Route) bool {
- if !isSameSubnet(a, b) || a.NIC != b.NIC {
- return false
- }
-
- aHasGW := len(a.Gateway) > 0 && !util.IsAny(a.Gateway)
- bHasGW := len(a.Gateway) > 0 && !util.IsAny(b.Gateway)
- if aHasGW && bHasGW {
- return a.Gateway == b.Gateway
- }
- // either one or both routes have no gateway
- return !aHasGW && !bHasGW
-}
diff --git a/src/connectivity/network/netstack/routes/routes_test.go b/src/connectivity/network/netstack/routes/routes_test.go
index 2dcf2c7..d45f7f2 100644
--- a/src/connectivity/network/netstack/routes/routes_test.go
+++ b/src/connectivity/network/netstack/routes/routes_test.go
@@ -10,7 +10,6 @@
"testing"
"netstack/routes"
- "netstack/util"
"github.com/google/netstack/tcpip"
)
@@ -32,10 +31,16 @@
}
func createRoute(nicid tcpip.NICID, subnet string, gateway string) tcpip.Route {
- _, s, _ := net.ParseCIDR(subnet)
+ _, s, err := net.ParseCIDR(subnet)
+ if err != nil {
+ panic(err)
+ }
+ sn, err := tcpip.NewSubnet(tcpip.Address(s.IP), tcpip.AddressMask(s.Mask))
+ if err != nil {
+ panic(err)
+ }
return tcpip.Route{
- Destination: tcpip.Address(s.IP),
- Mask: tcpip.AddressMask(s.Mask),
+ Destination: sn,
Gateway: ipStringToAddress(gateway),
NIC: nicid,
}
@@ -178,73 +183,13 @@
}
}
-func changeByte(b []byte) []byte {
- b[0] = ^b[0]
- return b
-}
-
-func TestIsSameRoute(t *testing.T) {
- gatewaysWithPrefix := []string{"127.0.0.1/32", "0.0.0.0/0", "123.220.3.14/14", "192.168.10.1/24",
- "::1/128", "::/128", "2605:143:32:113::1/64", "fe80:4234:242f:1111:5:243:5:4f/88"}
- nics := []tcpip.NICID{1, 2}
-
- for _, nic1 := range nics {
- t.Run(fmt.Sprintf("nic1=%d", nic1), func(t *testing.T) {
- for _, gp1 := range gatewaysWithPrefix {
- t.Run(fmt.Sprintf("gp1=%s", gp1), func(t *testing.T) {
- ip, s, err := net.ParseCIDR(gp1)
- if err != nil {
- t.Fatalf("net.ParseCIDR(%s) failed", gp1)
- }
- route1 := tcpip.Route{
- Destination: tcpip.Address(ipToAddress(s.IP)),
- Mask: tcpip.AddressMask(s.Mask),
- Gateway: tcpip.Address(ipToAddress(ip)),
- NIC: nic1,
- }
-
- if got := routes.IsSameRoute(route1, route1); got != true {
- t.Fatalf("got IsSameRoute(%s, %s) = %t, want = %t", routes.RouteStringer(&route1), routes.RouteStringer(&route1), got, true)
- }
- // Change the NIC
- route2 := route1
- route2.NIC = route1.NIC + 1
- if got := routes.IsSameRoute(route1, route2); got != false {
- t.Errorf("got IsSameRoute(%s, %s) = %t, want = %t", routes.RouteStringer(&route1), routes.RouteStringer(&route2), got, false)
- }
- // Change destination.
- route2 = route1
- route2.Destination = tcpip.Address(changeByte([]byte(route2.Destination)))
- if got := routes.IsSameRoute(route1, route2); got != false {
- t.Errorf("got IsSameRoute(%s, %s) = %t, want = %t", routes.RouteStringer(&route1), routes.RouteStringer(&route2), got, false)
- }
- // Change gateway.
- route2 = route1
- route2.Gateway = tcpip.Address(changeByte([]byte(route2.Gateway)))
- if got := routes.IsSameRoute(route1, route2); got != false {
- t.Errorf("got IsSameRoute(%s, %s) = %t, want = %t", routes.RouteStringer(&route1), routes.RouteStringer(&route2), got, false)
- }
- // Remove gateway if possible
- if !util.IsAny(route1.Gateway) {
- route2 = route1
- route2.Gateway = tcpip.Address("")
- if got := routes.IsSameRoute(route1, route2); got != false {
- t.Errorf("got IsSameRoute(%s, %s) = %t, want = %t", routes.RouteStringer(&route1), routes.RouteStringer(&route2), got, false)
- }
- }
- })
- }
- })
- }
-}
-
func isSameRouteTableImpl(rt1, rt2 []routes.ExtendedRoute, checkAttributes bool) bool {
if len(rt1) != len(rt2) {
return false
}
for i, r1 := range rt1 {
r2 := rt2[i]
- if !routes.IsSameRoute(r1.Route, r2.Route) {
+ if r1.Route != r2.Route {
return false
}
if checkAttributes && (r1.Metric != r2.Metric || r1.MetricTracksInterface != r2.MetricTracksInterface || r1.Dynamic != r2.Dynamic || r1.Enabled != r2.Enabled) {
@@ -333,21 +278,31 @@
r1 := createRoute(2, "0.0.0.0/0", "192.168.100.10")
// 1.test - r0 gets lower metric.
- tb := routes.RouteTable{}
- tb.AddRoute(r0, 100, true, true, true)
- tb.AddRoute(r1, 200, true, true, true)
- tableGot := tb.GetExtendedRouteTable()
- if !routes.IsSameRoute(r0, tableGot[0].Route) || !routes.IsSameRoute(r1, tableGot[1].Route) {
- t.Errorf("got %s, %s, want %s, %s", routes.RouteStringer(&tableGot[0].Route), routes.RouteStringer(&tableGot[1].Route), routes.RouteStringer(&r0), routes.RouteStringer(&r1))
+ {
+ var tb routes.RouteTable
+ tb.AddRoute(r0, 100, true, true, true)
+ tb.AddRoute(r1, 200, true, true, true)
+ tableGot := tb.GetExtendedRouteTable()
+ if got, want := tableGot[0].Route, r0; got != want {
+ t.Errorf("got = %s, want = %s", got, want)
+ }
+ if got, want := tableGot[1].Route, r1; got != want {
+ t.Errorf("got = %s, want = %s", got, want)
+ }
}
// 2.test - r1 gets lower metric.
- tb = routes.RouteTable{}
- tb.AddRoute(r0, 200, true, true, true)
- tb.AddRoute(r1, 100, true, true, true)
- tableGot = tb.GetExtendedRouteTable()
- if !routes.IsSameRoute(r0, tableGot[1].Route) || !routes.IsSameRoute(r1, tableGot[0].Route) {
- t.Errorf("got %s, %s, want %s, %s", routes.RouteStringer(&tableGot[0].Route), routes.RouteStringer(&tableGot[1].Route), routes.RouteStringer(&r1), routes.RouteStringer(&r0))
+ {
+ var tb routes.RouteTable
+ tb.AddRoute(r0, 200, true, true, true)
+ tb.AddRoute(r1, 100, true, true, true)
+ tableGot := tb.GetExtendedRouteTable()
+ if got, want := tableGot[0].Route, r1; got != want {
+ t.Errorf("got = %s, want = %s", got, want)
+ }
+ if got, want := tableGot[1].Route, r0; got != want {
+ t.Errorf("got = %s, want = %s", got, want)
+ }
}
})
}
@@ -434,17 +389,27 @@
tb := routes.RouteTable{}
tb.AddRoute(r0, 100, true, true, true)
tb.AddRoute(r1, 200, true, true, true)
- tableGot := tb.GetExtendedRouteTable()
- if !routes.IsSameRoute(r0, tableGot[0].Route) || !routes.IsSameRoute(r1, tableGot[1].Route) {
- t.Errorf("got %s, %s, want %s, %s", routes.RouteStringer(&tableGot[0].Route), routes.RouteStringer(&tableGot[1].Route), routes.RouteStringer(&r0), routes.RouteStringer(&r1))
+ {
+ tableGot := tb.GetExtendedRouteTable()
+ if got, want := tableGot[0].Route, r0; got != want {
+ t.Errorf("got = %s, want = %s", got, want)
+ }
+ if got, want := tableGot[1].Route, r1; got != want {
+ t.Errorf("got = %s, want = %s", got, want)
+ }
}
// Lowering nic1's metric should be reflected in r1's metric and promote it
// in the route table.
tb.UpdateMetricByInterface(1, 50)
- tableGot = tb.GetExtendedRouteTable()
- if !routes.IsSameRoute(r0, tableGot[1].Route) || !routes.IsSameRoute(r1, tableGot[0].Route) {
- t.Errorf("got %s, %s, want %s, %s", routes.RouteStringer(&tableGot[0].Route), routes.RouteStringer(&tableGot[1].Route), routes.RouteStringer(&r1), routes.RouteStringer(&r0))
+ {
+ tableGot := tb.GetExtendedRouteTable()
+ if got, want := tableGot[0].Route, r1; got != want {
+ t.Errorf("got = %s, want = %s", got, want)
+ }
+ if got, want := tableGot[1].Route, r0; got != want {
+ t.Errorf("got = %s, want = %s", got, want)
+ }
}
})
}
@@ -561,25 +526,24 @@
t.Run(tc.name, func(t *testing.T) {
// We have no way to directly disable routes in the route table, but we
// can use the Set() command to set a table with pre-disabled routes.
- testRouteTable2 := make([]routes.ExtendedRoute, len(testRouteTable))
- copy(testRouteTable2, testRouteTable)
+ testRouteTable := append([]routes.ExtendedRoute(nil), testRouteTable...)
// Disable a few routes.
for _, i := range tc.disabled {
- testRouteTable2[i].Enabled = false
+ testRouteTable[i].Enabled = false
}
- tb := routes.RouteTable{}
- tb.Set(testRouteTable2)
+ var tb routes.RouteTable
+ tb.Set(testRouteTable)
tableGot := tb.GetNetstackTable()
// Verify no disabled routes are in the Netstack table we got.
i := 0
- for _, r := range testRouteTable2 {
+ for _, r := range testRouteTable {
if r.Enabled {
- if !routes.IsSameRoute(tableGot[i], r.Route) {
- t.Errorf("got = %s, want = %s", routes.RouteStringer(&tableGot[i]), routes.RouteStringer(&r.Route))
+ if got, want := tableGot[i], r.Route; got != want {
+ t.Errorf("got = %s, want = %s", got, want)
}
- i += 1
+ i++
}
}
})
diff --git a/src/connectivity/network/netstack/socket_server.go b/src/connectivity/network/netstack/socket_server.go
index 3b973ee..af3cd69 100644
--- a/src/connectivity/network/netstack/socket_server.go
+++ b/src/connectivity/network/netstack/socket_server.go
@@ -170,7 +170,7 @@
return fmt.Errorf("Endpoint.Write(%s): %s", optsStr, err)
}
if ios.transProto != tcp.ProtocolNumber {
- if int(n) < len(v) {
+ if n < int64(len(v)) {
panic(fmt.Sprintf("UDP disallows short writes; saw: %d/%d", n, len(v)))
}
}
@@ -717,21 +717,30 @@
if err != nil {
return tcpipErrorToCode(tcpip.ErrBadAddress), nil
}
- if l := len(addr.Addr); l > 0 {
- if ios.netProto == ipv4.ProtocolNumber && l != header.IPv4AddressSize {
- syslog.VLogTf(syslog.DebugVerbosity, "connect", "%p: unsupported address %s", ios, addr.Addr)
- return C.EAFNOSUPPORT, nil
+ // NB: We can't just compare the length to zero because that would
+ // mishandle the IPv6-mapped IPv4 unspecified address.
+ disconnect := addr.Port == 0 && (len(addr.Addr) == 0 || net.IP(addr.Addr).IsUnspecified())
+ if disconnect {
+ if err := ios.ep.Disconnect(); err != nil {
+ return tcpipErrorToCode(err), nil
}
- }
- if err := ios.ep.Connect(addr); err != nil {
- if err == tcpip.ErrConnectStarted {
- localAddr, err := ios.ep.GetLocalAddress()
- if err != nil {
- panic(err)
+ } else {
+ if l := len(addr.Addr); l > 0 {
+ if ios.netProto == ipv4.ProtocolNumber && l != header.IPv4AddressSize {
+ syslog.VLogTf(syslog.DebugVerbosity, "connect", "%p: unsupported address %s", ios, addr.Addr)
+ return C.EAFNOSUPPORT, nil
}
- syslog.VLogTf(syslog.DebugVerbosity, "connect", "%p: started, local=%+v, addr=%+v", ios, localAddr, addr)
}
- return tcpipErrorToCode(err), nil
+ if err := ios.ep.Connect(addr); err != nil {
+ if err == tcpip.ErrConnectStarted {
+ localAddr, err := ios.ep.GetLocalAddress()
+ if err != nil {
+ panic(err)
+ }
+ syslog.VLogTf(syslog.DebugVerbosity, "connect", "%p: started, local=%+v, addr=%+v", ios, localAddr, addr)
+ }
+ return tcpipErrorToCode(err), nil
+ }
}
{
@@ -740,9 +749,7 @@
panic(err)
}
- // NB: We can't just compare the length to zero because that would
- // mishandle the IPv6-mapped IPv4 unspecified address.
- if len(addr.Addr) == 0 || net.IP(addr.Addr).IsUnspecified() {
+ if disconnect {
syslog.VLogTf(syslog.DebugVerbosity, "connect", "%p: local=%+v, remote=disconnected", ios, localAddr)
} else {
remoteAddr, err := ios.ep.GetRemoteAddress()
diff --git a/src/connectivity/network/netstack/util/parse.go b/src/connectivity/network/netstack/util/parse.go
index aac22b8..b43a8ad 100644
--- a/src/connectivity/network/netstack/util/parse.go
+++ b/src/connectivity/network/netstack/util/parse.go
@@ -6,7 +6,6 @@
package util
import (
- "fmt"
"net"
"github.com/google/netstack/tcpip"
@@ -25,51 +24,21 @@
return true
}
-func ApplyMask(addr tcpip.Address, mask tcpip.AddressMask) tcpip.Address {
- result := net.IP(addr).Mask(net.IPMask(mask))
- if result == nil {
- panic(fmt.Sprintf("net.IP(%s).Mask(%s) = nil", addr, mask))
- }
- return tcpip.Address(result)
-}
-
-func DefaultMask(addr tcpip.Address) tcpip.AddressMask {
- result := net.IP(addr).DefaultMask()
- if result == nil {
- panic(fmt.Sprintf("net.IP(%s).DefaultMask() = nil", addr))
- }
- return tcpip.AddressMask(result)
-}
-
-func CIDRMask(ones, bits int) tcpip.AddressMask {
- return tcpip.AddressMask(net.CIDRMask(ones, bits))
-}
-
-func PrefixLength(mask tcpip.AddressMask) int {
- bits, _ := net.IPMask(mask).Size()
- return bits
-}
-
-func ipToAddress(ip net.IP) tcpip.Address {
+// Parse parses the string representation of an IPv4 or IPv6 address.
+func Parse(src string) tcpip.Address {
+ ip := net.ParseIP(src)
if v4 := ip.To4(); v4 != nil {
return tcpip.Address(v4)
}
return tcpip.Address(ip)
}
-func ParseCIDR(s string) (tcpip.Address, tcpip.Subnet, error) {
- ip, subnet, err := net.ParseCIDR(s)
+// PointSubnet creates a subnet which contains only the passed address.
+func PointSubnet(a tcpip.Address) tcpip.Subnet {
+ l := len(a) * 8
+ subnet, err := tcpip.NewSubnet(a, tcpip.AddressMask(net.CIDRMask(l, l)))
if err != nil {
- return "", tcpip.Subnet{}, err
+ panic(err)
}
- sn, err := tcpip.NewSubnet(tcpip.Address(subnet.IP), tcpip.AddressMask(subnet.Mask))
- if err != nil {
- return "", tcpip.Subnet{}, err
- }
- return ipToAddress(ip), sn, nil
-}
-
-// Parse parses the string representation of an IPv4 or IPv6 address.
-func Parse(src string) tcpip.Address {
- return ipToAddress(net.ParseIP(src))
+ return subnet
}
diff --git a/src/connectivity/network/netstack/util/parse_test.go b/src/connectivity/network/netstack/util/parse_test.go
index 84371c7..f36c930 100644
--- a/src/connectivity/network/netstack/util/parse_test.go
+++ b/src/connectivity/network/netstack/util/parse_test.go
@@ -9,56 +9,6 @@
"github.com/google/netstack/tcpip"
)
-func TestApplyMask(t *testing.T) {
- tests := []struct {
- name string
- addr tcpip.Address
- mask tcpip.AddressMask
- want tcpip.Address
- shouldPanic bool
- }{
- {
- name: "fullMask",
- addr: "\x01\x01\x01\x01",
- mask: "\xff\xff\xff\xff",
- want: "\x01\x01\x01\x01",
- },
- {
- name: "partialMask",
- addr: "\x01\x01\x01\x01",
- mask: "\xff\xff\xff\x00",
- want: "\x01\x01\x01\x00",
- },
- {
- name: "mismatchedLengths",
- addr: "\x01\x01\x01\x01",
- mask: "\xff\xff\xff",
- shouldPanic: true,
- },
- {
- name: "zeroLengthMask",
- addr: "\x01\x01\x01\x01",
- mask: "",
- shouldPanic: true,
- },
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- defer func() {
- r := recover()
- if got := r != nil; got != test.shouldPanic {
- t.Logf("recover() = %s", r)
- t.Errorf("got (recover() != nil) = %t; want = %t", got, test.shouldPanic)
- }
- }()
- if got := util.ApplyMask(test.addr, test.mask); got != test.want {
- t.Errorf("got util.ApplyMask(%s, %s) = %s, want = %s", test.addr, test.mask, got, test.want)
- }
- })
- }
-}
-
func TestParse(t *testing.T) {
tests := []struct {
txt string
@@ -90,65 +40,6 @@
}
}
-func TestDefaultMask(t *testing.T) {
- tests := []struct {
- addr tcpip.Address
- mask tcpip.AddressMask
- shouldPanic bool
- }{
- {addr: util.Parse("192.168.42.10"), mask: "\xff\xff\xff\x00"},
- {addr: util.Parse("10.0.1.1"), mask: "\xff\x00\x00\x00"},
- {addr: util.Parse("10.0.1"), shouldPanic: true},
- {addr: util.Parse("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), shouldPanic: true},
- {addr: util.Parse(""), shouldPanic: true},
- }
-
- for _, test := range tests {
- func() {
- defer func() {
- r := recover()
- if got := r != nil; got != test.shouldPanic {
- t.Logf("recover() = %s", r)
- t.Errorf("got (recover() != nil) = %t; want = %t", got, test.shouldPanic)
- }
- }()
- got := util.DefaultMask(test.addr)
- if got != test.mask {
- t.Errorf("got util.DefaultMask(%q) = %q, want %q", test.addr, got, test.mask)
- }
- }()
- }
-}
-
-// Copied from pkg net (ip_test.go).
-func TestParseCIDR(t *testing.T) {
- for _, tt := range []struct {
- in string
- address string
- netmask string
- }{
- {"135.104.0.0/32", "135.104.0.0", "255.255.255.255"},
- {"0.0.0.0/24", "0.0.0.0", "255.255.255.0"},
- {"135.104.0.0/24", "135.104.0.0", "255.255.255.0"},
- {"135.104.0.1/32", "135.104.0.1", "255.255.255.255"},
- {"135.104.0.1/24", "135.104.0.1", "255.255.255.0"},
- } {
- address, subnet, err := util.ParseCIDR(tt.in)
- if err != nil {
- t.Error(err)
- } else if want := util.Parse(tt.address); address != want {
- t.Errorf("ParseCIDR('%s') = ('%s', _); want ('%s', _)", tt.in, address, want)
- } else {
- netmask := tcpip.AddressMask(util.Parse(tt.netmask))
- if want, err := tcpip.NewSubnet(util.ApplyMask(want, netmask), netmask); err != nil {
- t.Errorf("tcpip.NewSubnet('%v', '%v') failed: %v", want, tt.netmask, err)
- } else if want != subnet {
- t.Errorf("ParseCIDR('%s') = (_, %+v); want (_, %+v)", tt.in, subnet, want)
- }
- }
- }
-}
-
func TestIsAny(t *testing.T) {
for _, tc := range []struct {
name string
@@ -182,36 +73,3 @@
})
}
}
-
-func TestPrefixLength(t *testing.T) {
- for _, tc := range []struct {
- name string
- mask tcpip.AddressMask
- want int
- }{
- {"IPv4-Empty", "", 0},
- {"IPv4-0", "\x00\x00\x00\x00", 0},
- {"IPv4-3", "\xe0\x00\x00\x00", 3},
- {"IPv4-7", "\xfe\x00\x00\x00", 7},
- {"IPv4-8", "\xff\x00\x00\x00", 8},
- {"IPv4-12", "\xff\xf0\x00\x00", 12},
- {"IPv4-16", "\xff\xff\x00\x00", 16},
- {"IPv4-24", "\xff\xff\xff\x00", 24},
- {"IPv4-29", "\xff\xff\xff\xfc", 30},
- {"IPv4-32", "\xff\xff\xff\xff", 32},
- {"IPv6-Empty", "", 0},
- {"IPv6-0", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 0},
- {"IPv6-5", "\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 5},
- {"IPv6-8", "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 8},
- {"IPv6-22", "\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 22},
- {"IPv6-73", "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00", 73},
- {"IPv6-123", "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0", 123},
- {"IPv6-128", "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", 128},
- } {
- t.Run(tc.name, func(t *testing.T) {
- if got := util.PrefixLength(tc.mask); got != tc.want {
- t.Fatalf("PrefixLength(%v) = %v, want = %v", tc.mask, got, tc.want)
- }
- })
- }
-}
diff --git a/src/connectivity/network/tests/src/lib.rs b/src/connectivity/network/tests/src/lib.rs
index 0e5a4d8..ea95ace 100644
--- a/src/connectivity/network/tests/src/lib.rs
+++ b/src/connectivity/network/tests/src/lib.rs
@@ -43,14 +43,16 @@
name: &'static str,
endpoint_manager: &'a fidl_fuchsia_netemul_network::EndpointManagerProxy,
) -> std::result::Result<fidl_fuchsia_netemul_network::EndpointProxy, failure::Error> {
- let (status, endpoint) = endpoint_manager.create_endpoint(
- name,
- &mut fidl_fuchsia_netemul_network::EndpointConfig {
- mtu: 1500,
- mac: None,
- backing: fidl_fuchsia_netemul_network::EndpointBacking::Ethertap,
- },
- ).await
+ let (status, endpoint) = endpoint_manager
+ .create_endpoint(
+ name,
+ &mut fidl_fuchsia_netemul_network::EndpointConfig {
+ mtu: 1500,
+ mac: None,
+ backing: fidl_fuchsia_netemul_network::EndpointBacking::Ethertap,
+ },
+ )
+ .await
.context("failed to create endpoint")?;
let () = fuchsia_zircon::Status::ok(status).context("failed to create endpoint")?;
let endpoint = endpoint
@@ -161,8 +163,7 @@
let (client, server) = fidl::endpoints::create_proxy::<fidl_fuchsia_io::DirectoryMarker>()
.context("failed to create node proxy")?;
let () = netstack_proxy.get_aggregate_stats(server).context("failed to get aggregate stats")?;
- let dir_entries =
- files_async::readdir_recursive(&client).await.context("failed to readdir")?;
+ let dir_entries = files_async::readdir_recursive(&client).await.context("failed to readdir")?;
let path_segments: std::collections::hash_set::HashSet<usize> = dir_entries
.iter()
.map(|dir_entry| 1 + dir_entry.name.matches(std::path::MAIN_SEPARATOR).count())
@@ -181,18 +182,22 @@
name,
|netstack, device| {
async move {
- let id = netstack.add_ethernet_device(
- name,
- &mut fidl_fuchsia_netstack::InterfaceConfig {
- name: name.to_string(),
- filepath: "/fake/filepath/for_test".to_string(),
- metric: 0,
- ip_address_config: fidl_fuchsia_netstack::IpAddressConfig::Dhcp(true),
- },
- device,
- ).await
+ let id = netstack
+ .add_ethernet_device(
+ name,
+ &mut fidl_fuchsia_netstack::InterfaceConfig {
+ name: name.to_string(),
+ filepath: "/fake/filepath/for_test".to_string(),
+ metric: 0,
+ ip_address_config: fidl_fuchsia_netstack::IpAddressConfig::Dhcp(true),
+ },
+ device,
+ )
+ .await
.context("failed to add ethernet device")?;
- let interface = netstack.get_interfaces2().await
+ let interface = netstack
+ .get_interfaces2()
+ .await
.context("failed to get interfaces")?
.into_iter()
.find(|interface| interface.id == id)
@@ -205,38 +210,41 @@
Ok::<(), failure::Error>(())
}
},
- ).await
+ )
+ .await
}
#[fuchsia_async::run_singlethreaded(test)]
async fn add_ethernet_interface() -> Result {
let name = stringify!(add_ethernet_interface);
- with_netstack_and_device::<_, _, fidl_fuchsia_net_stack::StackMarker>(
- name,
- |stack, device| {
- async move {
- let (error, id) = stack.add_ethernet_interface(name, device).await
- .context("failed to add ethernet interface")?;
- assert_eq!(error, None);
- let interface = stack.list_interfaces().await
- .context("failed to list interfaces")?
- .into_iter()
- .find(|interface| interface.id == id)
- .ok_or(failure::err_msg("failed to find added ethernet interface"))?;
- assert_eq!(
- interface.properties.features
- & fidl_fuchsia_hardware_ethernet::INFO_FEATURE_LOOPBACK,
- 0
- );
- assert_eq!(
- interface.properties.physical_status,
- fidl_fuchsia_net_stack::PhysicalStatus::Down
- );
- Ok(())
- }
- },
- ).await
+ with_netstack_and_device::<_, _, fidl_fuchsia_net_stack::StackMarker>(name, |stack, device| {
+ async move {
+ let (error, id) = stack
+ .add_ethernet_interface(name, device)
+ .await
+ .context("failed to add ethernet interface")?;
+ assert_eq!(error, None);
+ let interface = stack
+ .list_interfaces()
+ .await
+ .context("failed to list interfaces")?
+ .into_iter()
+ .find(|interface| interface.id == id)
+ .ok_or(failure::err_msg("failed to find added ethernet interface"))?;
+ assert_eq!(
+ interface.properties.features
+ & fidl_fuchsia_hardware_ethernet::INFO_FEATURE_LOOPBACK,
+ 0
+ );
+ assert_eq!(
+ interface.properties.physical_status,
+ fidl_fuchsia_net_stack::PhysicalStatus::Down
+ );
+ Ok(())
+ }
+ })
+ .await
}
#[fuchsia_async::run_singlethreaded(test)]
@@ -266,11 +274,13 @@
}),
prefix_len: 32,
};
- let error = stack.add_interface_address(loopback.id, &mut interface_address).await
+ let error = stack
+ .add_interface_address(loopback.id, &mut interface_address)
+ .await
.context("failed to call add interface address")?;
assert_eq!(error.as_ref(), None);
- let (loopback, error) = stack.get_interface_info(loopback.id).await
- .context("failed to get loopback interface")?;
+ let (loopback, error) =
+ stack.get_interface_info(loopback.id).await.context("failed to get loopback interface")?;
assert_eq!(error.as_ref(), None);
let loopback = loopback.ok_or(failure::err_msg("failed to find loopback"))?;
@@ -281,11 +291,13 @@
loopback.properties.addresses
);
- let error = stack.del_interface_address(loopback.id, &mut interface_address).await
+ let error = stack
+ .del_interface_address(loopback.id, &mut interface_address)
+ .await
.context("failed to call del interface address")?;
assert_eq!(error.as_ref(), None);
- let (loopback, error) = stack.get_interface_info(loopback.id).await
- .context("failed to get loopback interface")?;
+ let (loopback, error) =
+ stack.get_interface_info(loopback.id).await.context("failed to get loopback interface")?;
assert_eq!(error.as_ref(), None);
let loopback = loopback.ok_or(failure::err_msg("failed to find loopback"))?;
@@ -321,7 +333,9 @@
};
// NET-2234 (crash on interface not found).
- let error = stack.add_interface_address(max_id + 1, &mut interface_address).await
+ let error = stack
+ .add_interface_address(max_id + 1, &mut interface_address)
+ .await
.context("failed to call add interface address")?
.ok_or(failure::err_msg("failed to get add interface address error"))?;
assert_eq!(
@@ -331,12 +345,14 @@
// NET-2334 (crash on invalid prefix length).
interface_address.prefix_len = 43;
- let error = stack.add_interface_address(max_id, &mut interface_address).await
+ let error = stack
+ .add_interface_address(max_id, &mut interface_address)
+ .await
.context("failed to call add interface address")?
.ok_or(failure::err_msg("failed to get add interface address error"))?;
assert_eq!(
error.as_ref(),
- &fidl_fuchsia_net_stack::Error { type_: fidl_fuchsia_net_stack::ErrorType::BadState }
+ &fidl_fuchsia_net_stack::Error { type_: fidl_fuchsia_net_stack::ErrorType::InvalidArgs }
);
Ok(())
@@ -356,8 +372,8 @@
.context("failed to connect to netstack")?;
let interfaces = stack.list_interfaces().await.context("failed to list interfaces")?;
let max_id = interfaces.iter().map(|interface| interface.id).max().unwrap_or(0);
- let (info, error) = stack.get_interface_info(max_id + 1).await
- .context("failed to call get interface info")?;
+ let (info, error) =
+ stack.get_interface_info(max_id + 1).await.context("failed to call get interface info")?;
assert_eq!(info, None);
let error = error.ok_or(failure::err_msg("failed to get get interface info error"))?;
assert_eq!(
@@ -422,32 +438,38 @@
let server_environment = create_netstack_environment(&sandbox, format!("{}_server", name))
.context("failed to create server environment")?;
let server_endpoint_name = "server";
- let server_endpoint = create_endpoint(server_endpoint_name, &endpoint_manager).await
+ let server_endpoint = create_endpoint(server_endpoint_name, &endpoint_manager)
+ .await
.context("failed to create endpoint")?;
- let () =
- server_endpoint.set_link_up(true).await.context("failed to start server endpoint")?;
+ let () = server_endpoint.set_link_up(true).await.context("failed to start server endpoint")?;
{
- let server_device = server_endpoint.get_ethernet_device().await
+ let server_device = server_endpoint
+ .get_ethernet_device()
+ .await
.context("failed to get server ethernet device")?;
let server_stack =
connect_to_service::<fidl_fuchsia_net_stack::StackMarker>(&server_environment)
.context("failed to connect to server stack")?;
- let (error, id) = server_stack.add_ethernet_interface(name, server_device).await
+ let (error, id) = server_stack
+ .add_ethernet_interface(name, server_device)
+ .await
.context("failed to add server ethernet interface")?;
assert_eq!(error, None);
- let error = server_stack.add_interface_address(
- id,
- &mut fidl_fuchsia_net_stack::InterfaceAddress {
- ip_address: fidl_fuchsia_net::IpAddress::Ipv4(fidl_fuchsia_net::Ipv4Address {
- addr: [192, 168, 0, 1],
- }),
- prefix_len: 24,
- },
- ).await
+ let error = server_stack
+ .add_interface_address(
+ id,
+ &mut fidl_fuchsia_net_stack::InterfaceAddress {
+ ip_address: fidl_fuchsia_net::IpAddress::Ipv4(fidl_fuchsia_net::Ipv4Address {
+ addr: [192, 168, 0, 1],
+ }),
+ prefix_len: 24,
+ },
+ )
+ .await
.context("failed to add interface address")?;
assert_eq!(error, None);
- let error = server_stack.enable_interface(id).await
- .context("failed to enable server interface")?;
+ let error =
+ server_stack.enable_interface(id).await.context("failed to enable server interface")?;
assert_eq!(error, None);
}
let launcher = {
@@ -465,10 +487,10 @@
let client_environment = create_netstack_environment(&sandbox, format!("{}_client", name))
.context("failed to create client environment")?;
let client_endpoint_name = "client";
- let client_endpoint = create_endpoint(client_endpoint_name, &endpoint_manager).await
+ let client_endpoint = create_endpoint(client_endpoint_name, &endpoint_manager)
+ .await
.context("failed to create endpoint")?;
- let () =
- client_endpoint.set_link_up(true).await.context("failed to start client endpoint")?;
+ let () = client_endpoint.set_link_up(true).await.context("failed to start client endpoint")?;
let network_manager = {
let (client, server) =
@@ -479,43 +501,55 @@
client
};
- let (status, network) = network_manager.create_network(
- name,
- fidl_fuchsia_netemul_network::NetworkConfig {
- latency: None,
- packet_loss: None,
- reorder: None,
- },
- ).await
+ let (status, network) = network_manager
+ .create_network(
+ name,
+ fidl_fuchsia_netemul_network::NetworkConfig {
+ latency: None,
+ packet_loss: None,
+ reorder: None,
+ },
+ )
+ .await
.context("failed to create network")?;
let network = network
.ok_or(failure::err_msg("failed to create network"))?
.into_proxy()
.context("failed to get network proxy")?;
let () = fuchsia_zircon::Status::ok(status).context("failed to create network")?;
- let status = network.attach_endpoint(server_endpoint_name).await
+ let status = network
+ .attach_endpoint(server_endpoint_name)
+ .await
.context("failed to attach server endpoint")?;
let () = fuchsia_zircon::Status::ok(status).context("failed to attach server endpoint")?;
- let status = network.attach_endpoint(client_endpoint_name).await
+ let status = network
+ .attach_endpoint(client_endpoint_name)
+ .await
.context("failed to attach client endpoint")?;
let () = fuchsia_zircon::Status::ok(status).context("failed to attach client endpoint")?;
{
- let client_device = client_endpoint.get_ethernet_device().await
+ let client_device = client_endpoint
+ .get_ethernet_device()
+ .await
.context("failed to get client ethernet device")?;
let client_stack =
connect_to_service::<fidl_fuchsia_net_stack::StackMarker>(&client_environment)
.context("failed to connect to client stack")?;
- let (error, id) = client_stack.add_ethernet_interface(name, client_device).await
+ let (error, id) = client_stack
+ .add_ethernet_interface(name, client_device)
+ .await
.context("failed to add client ethernet interface")?;
assert_eq!(error, None);
- let error = client_stack.enable_interface(id).await
- .context("failed to enable client interface")?;
+ let error =
+ client_stack.enable_interface(id).await.context("failed to enable client interface")?;
assert_eq!(error, None);
let client_netstack =
connect_to_service::<fidl_fuchsia_netstack::NetstackMarker>(&client_environment)
.context("failed to connect to client netstack")?;
- let error = client_netstack.set_dhcp_client_status(id as u32, true).await
+ let error = client_netstack
+ .set_dhcp_client_status(id as u32, true)
+ .await
.context("failed to set DHCP client status")?;
assert_eq!(error.status, fidl_fuchsia_netstack::Status::Ok, "{}", error.message);
@@ -552,7 +586,8 @@
fuchsia_async::Time::after(fuchsia_zircon::Duration::from_seconds(60)),
|| None,
);
- let (addr, netmask) = address_change.await
+ let (addr, netmask) = address_change
+ .await
.ok_or(failure::err_msg("failed to observe DHCP acquisition"))?
.context("failed to observe DHCP acquisition")?;
assert_eq!(