]> Cypherpunks repositories - gostls13.git/commitdiff
net: fix multicast and IPv6 related issues on Plan 9
authorFazlul Shahriar <fshahriar@gmail.com>
Wed, 16 Oct 2019 02:58:40 +0000 (22:58 -0400)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 16 Oct 2019 17:46:16 +0000 (17:46 +0000)
Fix issues that make these tests pass:
- TestDialerLocalAddr: return error if local address is not IPv4 for
"tcp4" network.
- TestInterfaceAddrs, TestInterfaceUnicastAddrs: don't assume each
interface has only one address. It may have more than one or none.
- TestConcurrentPreferGoResolversDial: should be skipped on Plan 9.
- TestListenMulticastUDP: remove IP from `announce` command and don't
mix IPv4 address with IPv6 address in `addmulti` command.

Fixes #34931

Change-Id: Ie0fdfe19ea282e5d6d6c938bf3c9139f8f5b0308
Reviewed-on: https://go-review.googlesource.com/c/go/+/201397
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/net/interface_plan9.go
src/net/ipsock_plan9.go
src/net/lookup_test.go
src/net/tcpsock_plan9.go
src/net/udpsock_plan9.go
src/net/udpsock_plan9_test.go

index 8fe913840649df038936e1b37f148b37ab6e20a0..1295017a1b9fec7b5bc13a422584b1ac071033c9 100644 (file)
@@ -143,8 +143,8 @@ func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
                ifcs = []Interface{*ifi}
        }
 
-       addrs := make([]Addr, len(ifcs))
-       for i, ifc := range ifcs {
+       var addrs []Addr
+       for _, ifc := range ifcs {
                status := ifc.Name + "/status"
                statusf, err := open(status)
                if err != nil {
@@ -157,39 +157,36 @@ func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
                if _, ok := statusf.readLine(); !ok {
                        return nil, errors.New("cannot read header line for interface: " + status)
                }
-               line, ok := statusf.readLine()
-               if !ok {
-                       return nil, errors.New("cannot read IP address for interface: " + status)
-               }
 
-               // This assumes only a single address for the interface.
-               fields := getFields(line)
-               if len(fields) < 1 {
-                       return nil, errors.New("cannot parse IP address for interface: " + status)
-               }
-               addr := fields[0]
-               ip := ParseIP(addr)
-               if ip == nil {
-                       return nil, errors.New("cannot parse IP address for interface: " + status)
-               }
+               for line, ok := statusf.readLine(); ok; line, ok = statusf.readLine() {
+                       fields := getFields(line)
+                       if len(fields) < 1 {
+                               return nil, errors.New("cannot parse IP address for interface: " + status)
+                       }
+                       addr := fields[0]
+                       ip := ParseIP(addr)
+                       if ip == nil {
+                               return nil, errors.New("cannot parse IP address for interface: " + status)
+                       }
 
-               // The mask is represented as CIDR relative to the IPv6 address.
-               // Plan 9 internal representation is always IPv6.
-               maskfld := fields[1]
-               maskfld = maskfld[1:]
-               pfxlen, _, ok := dtoi(maskfld)
-               if !ok {
-                       return nil, errors.New("cannot parse network mask for interface: " + status)
-               }
-               var mask IPMask
-               if ip.To4() != nil { // IPv4 or IPv6 IPv4-mapped address
-                       mask = CIDRMask(pfxlen-8*len(v4InV6Prefix), 8*IPv4len)
-               }
-               if ip.To16() != nil && ip.To4() == nil { // IPv6 address
-                       mask = CIDRMask(pfxlen, 8*IPv6len)
-               }
+                       // The mask is represented as CIDR relative to the IPv6 address.
+                       // Plan 9 internal representation is always IPv6.
+                       maskfld := fields[1]
+                       maskfld = maskfld[1:]
+                       pfxlen, _, ok := dtoi(maskfld)
+                       if !ok {
+                               return nil, errors.New("cannot parse network mask for interface: " + status)
+                       }
+                       var mask IPMask
+                       if ip.To4() != nil { // IPv4 or IPv6 IPv4-mapped address
+                               mask = CIDRMask(pfxlen-8*len(v4InV6Prefix), 8*IPv4len)
+                       }
+                       if ip.To16() != nil && ip.To4() == nil { // IPv6 address
+                               mask = CIDRMask(pfxlen, 8*IPv6len)
+                       }
 
-               addrs[i] = &IPNet{IP: ip, Mask: mask}
+                       addrs = append(addrs, &IPNet{IP: ip, Mask: mask})
+               }
        }
 
        return addrs, nil
index d226585e086f80c9d01e345b0ed1c1b35fa4b220..93f0f4eec36cf0c3b5358ef4779db2973ac7501d 100644 (file)
@@ -227,7 +227,7 @@ func listenPlan9(ctx context.Context, net string, laddr Addr) (fd *netFD, err er
        _, err = f.WriteString("announce " + dest)
        if err != nil {
                f.Close()
-               return nil, err
+               return nil, &OpError{Op: "announce", Net: net, Source: laddr, Addr: nil, Err: err}
        }
        laddr, err = readPlan9Addr(proto, netdir+"/"+proto+"/"+name+"/local")
        if err != nil {
index dc8a0839b9bf65a63857de968587bde1d5dcecff..8a41510daf3ece4d5184482f79554ce9c7ad6670 100644 (file)
@@ -972,10 +972,11 @@ func (lcr *lookupCustomResolver) dial() func(ctx context.Context, network, addre
 // TestConcurrentPreferGoResolversDial tests that multiple resolvers with the
 // PreferGo option used concurrently are all dialed properly.
 func TestConcurrentPreferGoResolversDial(t *testing.T) {
-       // The windows implementation of the resolver does not use the Dial
-       // function.
-       if runtime.GOOS == "windows" {
-               t.Skip("skip on windows")
+       // The windows and plan9 implementation of the resolver does not use
+       // the Dial function.
+       switch runtime.GOOS {
+       case "windows", "plan9":
+               t.Skipf("skip on %v", runtime.GOOS)
        }
 
        testenv.MustHaveExternalNetwork(t)
index e2e835957c0396dec4225134417a382552b59c49..768d03b06cefa0ab96bea21859226fae1023eef6 100644 (file)
@@ -23,7 +23,12 @@ func (sd *sysDialer) dialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPCo
 
 func (sd *sysDialer) doDialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
        switch sd.network {
-       case "tcp", "tcp4", "tcp6":
+       case "tcp4":
+               // Plan 9 doesn't complain about [::]:0->127.0.0.1, so it's up to us.
+               if laddr != nil && len(laddr.IP) != 0 && laddr.IP.To4() == nil {
+                       return nil, &AddrError{Err: "non-IPv4 local address", Addr: laddr.String()}
+               }
+       case "tcp", "tcp6":
        default:
                return nil, UnknownNetworkError(sd.network)
        }
index 563d943507e44e7ddd0384df74f695e0d98b992d..79986ce4da2891beeef3624a1f6e9a24fb15dffa 100644 (file)
@@ -109,7 +109,9 @@ func (sl *sysListener) listenUDP(ctx context.Context, laddr *UDPAddr) (*UDPConn,
 }
 
 func (sl *sysListener) listenMulticastUDP(ctx context.Context, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
-       l, err := listenPlan9(ctx, sl.network, gaddr)
+       // Plan 9 does not like announce command with a multicast address,
+       // so do not specify an IP address when listening.
+       l, err := listenPlan9(ctx, sl.network, &UDPAddr{IP: nil, Port: gaddr.Port, Zone: gaddr.Zone})
        if err != nil {
                return nil, err
        }
@@ -129,11 +131,13 @@ func (sl *sysListener) listenMulticastUDP(ctx context.Context, ifi *Interface, g
                        return nil, err
                }
        }
+
+       have4 := gaddr.IP.To4() != nil
        for _, addr := range addrs {
-               if ipnet, ok := addr.(*IPNet); ok {
+               if ipnet, ok := addr.(*IPNet); ok && (ipnet.IP.To4() != nil) == have4 {
                        _, err = l.ctl.WriteString("addmulti " + ipnet.IP.String() + " " + gaddr.IP.String())
                        if err != nil {
-                               return nil, err
+                               return nil, &OpError{Op: "addmulti", Net: "", Source: nil, Addr: ipnet, Err: err}
                        }
                }
        }
index 09f5a5dc65463bf545b19e45288af2abe49dbedf..3febfcc07414142b3f769aec0e6300c53948b8b2 100644 (file)
@@ -36,7 +36,7 @@ func TestListenMulticastUDP(t *testing.T) {
 
        c1, err := ListenMulticastUDP("udp4", mifc, &UDPAddr{IP: ParseIP("224.0.0.254")})
        if err != nil {
-               t.Fatalf("multicast not working on %s", runtime.GOOS)
+               t.Fatalf("multicast not working on %s: %v", runtime.GOOS, err)
        }
        c1addr := c1.LocalAddr().(*UDPAddr)
        if err != nil {