--- /dev/null
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "go/ast"
+
+func init() {
+ register(netipv6zoneFix)
+}
+
+var netipv6zoneFix = fix{
+ "netipv6zone",
+ "2012-11-26",
+ netipv6zone,
+ `Adapt element key to IPNet, IPAddr, UDPAddr or TCPAddr composite literals.
+
+https://codereview.appspot.com/6849045/
+`,
+}
+
+func netipv6zone(f *ast.File) bool {
+ if !imports(f, "net") {
+ return false
+ }
+
+ fixed := false
+ walk(f, func(n interface{}) {
+ cl, ok := n.(*ast.CompositeLit)
+ if !ok {
+ return
+ }
+ se, ok := cl.Type.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+ if !isTopName(se.X, "net") || se.Sel == nil {
+ return
+ }
+ switch ss := se.Sel.String(); ss {
+ case "IPNet", "IPAddr", "UDPAddr", "TCPAddr":
+ for i, e := range cl.Elts {
+ if _, ok := e.(*ast.KeyValueExpr); ok {
+ break
+ }
+ switch i {
+ case 0:
+ cl.Elts[i] = &ast.KeyValueExpr{
+ Key: ast.NewIdent("IP"),
+ Value: e,
+ }
+ case 1:
+ if ss == "IPNet" {
+ cl.Elts[i] = &ast.KeyValueExpr{
+ Key: ast.NewIdent("Mask"),
+ Value: e,
+ }
+ } else {
+ cl.Elts[i] = &ast.KeyValueExpr{
+ Key: ast.NewIdent("Port"),
+ Value: e,
+ }
+ }
+ }
+ fixed = true
+ }
+ }
+ })
+ return fixed
+}
--- /dev/null
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func init() {
+ addTestCases(netipv6zoneTests, netipv6zone)
+}
+
+var netipv6zoneTests = []testCase{
+ {
+ Name: "netipv6zone.0",
+ In: `package main
+
+import "net"
+
+var a = []struct {
+ *net.IPNet
+}{
+ &net.IPNet{net.ParseIP("2001:DB8::"), net.IPMask(net.ParseIP("ffff:ffff:ffff::"))},
+}
+
+func f() net.Addr {
+ b := net.IPNet{net.IPv4(127, 0, 0, 1), net.IPv4Mask(255, 0, 0, 0)}
+ c := &net.IPAddr{ip1}
+ sub(&net.UDPAddr{ip2, 12345})
+ d := &net.TCPAddr{IP: ip3, Port: 54321}
+ return &net.TCPAddr{ip4}, nil
+}
+`,
+ Out: `package main
+
+import "net"
+
+var a = []struct {
+ *net.IPNet
+}{
+ &net.IPNet{IP: net.ParseIP("2001:DB8::"), Mask: net.IPMask(net.ParseIP("ffff:ffff:ffff::"))},
+}
+
+func f() net.Addr {
+ b := net.IPNet{IP: net.IPv4(127, 0, 0, 1), Mask: net.IPv4Mask(255, 0, 0, 0)}
+ c := &net.IPAddr{IP: ip1}
+ sub(&net.UDPAddr{IP: ip2, Port: 12345})
+ d := &net.TCPAddr{IP: ip3, Port: 54321}
+ return &net.TCPAddr{IP: ip4}, nil
+}
+`,
+ },
+}
type IPNet struct {
IP IP // network number
Mask IPMask // network mask
+ Zone string // IPv6 scoped addressing zone
}
// IPv4 returns the IP address (in 16-byte form) of the
return nil, nil, &ParseError{"CIDR address", s}
}
m := CIDRMask(n, 8*iplen)
- return ip, &IPNet{ip.Mask(m), m}, nil
+ return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil
}
net *IPNet
err error
}{
- {"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 255)}, nil},
- {"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet{IPv4(0, 0, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
- {"135.104.0.0/24", IPv4(135, 104, 0, 0), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
- {"135.104.0.1/32", IPv4(135, 104, 0, 1), &IPNet{IPv4(135, 104, 0, 1), IPv4Mask(255, 255, 255, 255)}, nil},
- {"135.104.0.1/24", IPv4(135, 104, 0, 1), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
- {"::1/128", ParseIP("::1"), &IPNet{ParseIP("::1"), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))}, nil},
- {"abcd:2345::/127", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"))}, nil},
- {"abcd:2345::/65", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::"))}, nil},
- {"abcd:2345::/64", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff::"))}, nil},
- {"abcd:2345::/63", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:fffe::"))}, nil},
- {"abcd:2345::/33", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:8000::"))}, nil},
- {"abcd:2345::/32", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff::"))}, nil},
- {"abcd:2344::/31", ParseIP("abcd:2344::"), &IPNet{ParseIP("abcd:2344::"), IPMask(ParseIP("ffff:fffe::"))}, nil},
- {"abcd:2300::/24", ParseIP("abcd:2300::"), &IPNet{ParseIP("abcd:2300::"), IPMask(ParseIP("ffff:ff00::"))}, nil},
- {"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2300::"), IPMask(ParseIP("ffff:ff00::"))}, nil},
- {"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet{ParseIP("2001:DB8::"), IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
- {"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet{ParseIP("2001:DB8::"), IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
+ {"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 255)}, nil},
+ {"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet{IP: IPv4(0, 0, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
+ {"135.104.0.0/24", IPv4(135, 104, 0, 0), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
+ {"135.104.0.1/32", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 1), Mask: IPv4Mask(255, 255, 255, 255)}, nil},
+ {"135.104.0.1/24", IPv4(135, 104, 0, 1), &IPNet{IP: IPv4(135, 104, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)}, nil},
+ {"::1/128", ParseIP("::1"), &IPNet{IP: ParseIP("::1"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))}, nil},
+ {"abcd:2345::/127", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"))}, nil},
+ {"abcd:2345::/65", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::"))}, nil},
+ {"abcd:2345::/64", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff::"))}, nil},
+ {"abcd:2345::/63", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:fffe::"))}, nil},
+ {"abcd:2345::/33", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff:8000::"))}, nil},
+ {"abcd:2345::/32", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2345::"), Mask: IPMask(ParseIP("ffff:ffff::"))}, nil},
+ {"abcd:2344::/31", ParseIP("abcd:2344::"), &IPNet{IP: ParseIP("abcd:2344::"), Mask: IPMask(ParseIP("ffff:fffe::"))}, nil},
+ {"abcd:2300::/24", ParseIP("abcd:2300::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil},
+ {"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil},
+ {"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
+ {"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
{"192.168.1.1/255.255.255.0", nil, nil, &ParseError{"CIDR address", "192.168.1.1/255.255.255.0"}},
{"192.168.1.1/35", nil, nil, &ParseError{"CIDR address", "192.168.1.1/35"}},
{"2001:db8::1/-1", nil, nil, &ParseError{"CIDR address", "2001:db8::1/-1"}},
net *IPNet
ok bool
}{
- {IPv4(172, 16, 1, 1), &IPNet{IPv4(172, 16, 0, 0), CIDRMask(12, 32)}, true},
- {IPv4(172, 24, 0, 1), &IPNet{IPv4(172, 16, 0, 0), CIDRMask(13, 32)}, false},
- {IPv4(192, 168, 0, 3), &IPNet{IPv4(192, 168, 0, 0), IPv4Mask(0, 0, 255, 252)}, true},
- {IPv4(192, 168, 0, 4), &IPNet{IPv4(192, 168, 0, 0), IPv4Mask(0, 255, 0, 252)}, false},
- {ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:1::"), CIDRMask(47, 128)}, true},
- {ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:2::"), CIDRMask(47, 128)}, false},
- {ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:1::"), IPMask(ParseIP("ffff:0:ffff::"))}, true},
- {ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:1::"), IPMask(ParseIP("0:0:0:ffff::"))}, false},
+ {IPv4(172, 16, 1, 1), &IPNet{IP: IPv4(172, 16, 0, 0), Mask: CIDRMask(12, 32)}, true},
+ {IPv4(172, 24, 0, 1), &IPNet{IP: IPv4(172, 16, 0, 0), Mask: CIDRMask(13, 32)}, false},
+ {IPv4(192, 168, 0, 3), &IPNet{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(0, 0, 255, 252)}, true},
+ {IPv4(192, 168, 0, 4), &IPNet{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(0, 255, 0, 252)}, false},
+ {ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: CIDRMask(47, 128)}, true},
+ {ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:2::"), Mask: CIDRMask(47, 128)}, false},
+ {ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: IPMask(ParseIP("ffff:0:ffff::"))}, true},
+ {ParseIP("2001:db8:1:2::1"), &IPNet{IP: ParseIP("2001:db8:1::"), Mask: IPMask(ParseIP("0:0:0:ffff::"))}, false},
}
func TestIPNetContains(t *testing.T) {
in *IPNet
out string
}{
- {&IPNet{IPv4(192, 168, 1, 0), CIDRMask(26, 32)}, "192.168.1.0/26"},
- {&IPNet{IPv4(192, 168, 1, 0), IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
- {&IPNet{ParseIP("2001:db8::"), CIDRMask(55, 128)}, "2001:db8::/55"},
- {&IPNet{ParseIP("2001:db8::"), IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
+ {&IPNet{IP: IPv4(192, 168, 1, 0), Mask: CIDRMask(26, 32)}, "192.168.1.0/26"},
+ {&IPNet{IP: IPv4(192, 168, 1, 0), Mask: IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
+ {&IPNet{IP: ParseIP("2001:db8::"), Mask: CIDRMask(55, 128)}, "2001:db8::/55"},
+ {&IPNet{IP: ParseIP("2001:db8::"), Mask: IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
}
func TestIPNetString(t *testing.T) {
in IPNet
out IPNet
}{
- {IPNet{v4addr, v4mask}, IPNet{v4addr, v4mask}},
- {IPNet{v4addr, v4mappedv6mask}, IPNet{v4addr, v4mask}},
- {IPNet{v4mappedv6addr, v4mappedv6mask}, IPNet{v4addr, v4mask}},
- {IPNet{v4mappedv6addr, v6mask}, IPNet{v4addr, v4maskzero}},
- {IPNet{v4addr, v6mask}, IPNet{v4addr, v4maskzero}},
- {IPNet{v6addr, v6mask}, IPNet{v6addr, v6mask}},
- {IPNet{v6addr, v4mappedv6mask}, IPNet{v6addr, v4mappedv6mask}},
- {in: IPNet{v6addr, v4mask}},
- {in: IPNet{v4addr, badmask}},
- {in: IPNet{v4mappedv6addr, badmask}},
- {in: IPNet{v6addr, badmask}},
- {in: IPNet{badaddr, v4mask}},
- {in: IPNet{badaddr, v4mappedv6mask}},
- {in: IPNet{badaddr, v6mask}},
- {in: IPNet{badaddr, badmask}},
+ {IPNet{IP: v4addr, Mask: v4mask}, IPNet{IP: v4addr, Mask: v4mask}},
+ {IPNet{IP: v4addr, Mask: v4mappedv6mask}, IPNet{IP: v4addr, Mask: v4mask}},
+ {IPNet{IP: v4mappedv6addr, Mask: v4mappedv6mask}, IPNet{IP: v4addr, Mask: v4mask}},
+ {IPNet{IP: v4mappedv6addr, Mask: v6mask}, IPNet{IP: v4addr, Mask: v4maskzero}},
+ {IPNet{IP: v4addr, Mask: v6mask}, IPNet{IP: v4addr, Mask: v4maskzero}},
+ {IPNet{IP: v6addr, Mask: v6mask}, IPNet{IP: v6addr, Mask: v6mask}},
+ {IPNet{IP: v6addr, Mask: v4mappedv6mask}, IPNet{IP: v6addr, Mask: v4mappedv6mask}},
+ {in: IPNet{IP: v6addr, Mask: v4mask}},
+ {in: IPNet{IP: v4addr, Mask: badmask}},
+ {in: IPNet{IP: v4mappedv6addr, Mask: badmask}},
+ {in: IPNet{IP: v6addr, Mask: badmask}},
+ {in: IPNet{IP: badaddr, Mask: v4mask}},
+ {in: IPNet{IP: badaddr, Mask: v4mappedv6mask}},
+ {in: IPNet{IP: badaddr, Mask: v6mask}},
+ {in: IPNet{IP: badaddr, Mask: badmask}},
}
func TestNetworkNumberAndMask(t *testing.T) {
for _, tt := range networknumberandmasktests {
ip, m := networkNumberAndMask(&tt.in)
- out := &IPNet{ip, m}
+ out := &IPNet{IP: ip, Mask: m}
if !reflect.DeepEqual(&tt.out, out) {
t.Errorf("networkNumberAndMask(%v) = %v; want %v", tt.in, out, &tt.out)
}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// (Raw) IP sockets
+// Raw IP sockets
package net
// IPAddr represents the address of an IP end point.
type IPAddr struct {
- IP IP
+ IP IP
+ Zone string // IPv6 scoped addressing zone
}
// Network returns the address's network name, "ip".
if err != nil {
return nil, err
}
- return &IPAddr{ip}, nil
+ return &IPAddr{IP: ip}, nil
}
// Convert "host" into IP address.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// (Raw) IP sockets stubs for Plan 9
+// Raw IP sockets for Plan 9
package net
return syscall.EPLAN9
}
-// IP-specific methods.
-
// ReadFromIP reads an IP packet from c, copying the payload into b.
// It returns the number of bytes copied into b and the return address
// that was on the packet.
// +build darwin freebsd linux netbsd openbsd windows
-// (Raw) IP sockets
+// Raw IP sockets for POSIX
package net
func sockaddrToIP(sa syscall.Sockaddr) Addr {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
- return &IPAddr{sa.Addr[0:]}
+ return &IPAddr{IP: sa.Addr[0:]}
case *syscall.SockaddrInet6:
- return &IPAddr{sa.Addr[0:]}
+ return &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
}
return nil
}
}
func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
- return ipToSockaddr(family, a.IP, 0)
+ return ipToSockaddr(family, a.IP, 0, a.Zone)
}
func (a *IPAddr) toAddr() sockaddr {
func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
-// IP-specific methods.
-
// ReadFromIP reads an IP packet from c, copying the payload into b.
// It returns the number of bytes copied into b and the return address
// that was on the packet.
n, sa, err := c.fd.ReadFrom(b)
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
- addr = &IPAddr{sa.Addr[0:]}
+ addr = &IPAddr{IP: sa.Addr[0:]}
if len(b) >= IPv4len { // discard ipv4 header
hsize := (int(b[0]) & 0xf) * 4
copy(b, b[hsize:])
n -= hsize
}
case *syscall.SockaddrInet6:
- addr = &IPAddr{sa.Addr[0:]}
+ addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
}
return n, addr, err
}
if !c.ok() {
return 0, nil, syscall.EINVAL
}
- n, uaddr, err := c.ReadFromIP(b)
- return n, uaddr.toAddr(), err
+ n, addr, err := c.ReadFromIP(b)
+ return n, addr.toAddr(), err
}
// ReadMsgIP reads a packet from c, copying the payload into b and the
n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
- addr = &IPAddr{sa.Addr[0:]}
+ addr = &IPAddr{IP: sa.Addr[0:]}
case *syscall.SockaddrInet6:
- addr = &IPAddr{sa.Addr[0:]}
+ addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
}
return
}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// IP sockets
+// Internet protocol family sockets
package net
return addr, p, nil
}
+
+func zoneToString(zone int) string {
+ if zone == 0 {
+ return ""
+ }
+ if ifi, err := InterfaceByIndex(zone); err == nil {
+ return ifi.Name
+ }
+ return itod(uint(zone))
+}
+
+func zoneToInt(zone string) int {
+ if zone == "" {
+ return 0
+ }
+ if ifi, err := InterfaceByName(zone); err == nil {
+ return ifi.Index
+ }
+ n, _, _ := dtoi(zone, 0)
+ return n
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// IP sockets stubs for Plan 9
+// Internet protocol family sockets for Plan 9
package net
}
switch proto {
case "tcp":
- addr = &TCPAddr{ip, port}
+ addr = &TCPAddr{IP: ip, Port: port}
case "udp":
- addr = &UDPAddr{ip, port}
+ addr = &UDPAddr{IP: ip, Port: port}
default:
return nil, errors.New("unknown protocol " + proto)
}
// +build darwin freebsd linux netbsd openbsd windows
+// Internet protocol family sockets for POSIX
+
package net
import (
return nil, &OpError{mode, net, addr, err}
}
-func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, error) {
+func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
switch family {
case syscall.AF_INET:
if len(ip) == 0 {
if ip = ip.To4(); ip == nil {
return nil, InvalidAddrError("non-IPv4 address")
}
- s := new(syscall.SockaddrInet4)
+ sa := new(syscall.SockaddrInet4)
for i := 0; i < IPv4len; i++ {
- s.Addr[i] = ip[i]
+ sa.Addr[i] = ip[i]
}
- s.Port = port
- return s, nil
+ sa.Port = port
+ return sa, nil
case syscall.AF_INET6:
if len(ip) == 0 {
ip = IPv6zero
if ip = ip.To16(); ip == nil {
return nil, InvalidAddrError("non-IPv6 address")
}
- s := new(syscall.SockaddrInet6)
+ sa := new(syscall.SockaddrInet6)
for i := 0; i < IPv6len; i++ {
- s.Addr[i] = ip[i]
+ sa.Addr[i] = ip[i]
}
- s.Port = port
- return s, nil
+ sa.Port = port
+ sa.ZoneId = uint32(zoneToInt(zone))
+ return sa, nil
}
return nil, InvalidAddrError("unexpected socket family")
}
}{
// cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers
- {"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false},
- {"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, 0, false},
- {"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true},
- {"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, 0, true},
+ {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, FlagUp | FlagLoopback, false},
+ {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, 0, false},
+ {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+ {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, 0, true},
- {"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false},
- {"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, 0, false},
+ {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, FlagUp | FlagLoopback, false},
+ {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, 0, false},
- {"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, 0, true},
- {"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, 0, true},
- {"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, 0, true},
- {"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, 0, true},
- {"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, 0, true},
- {"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, 0, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}, 0, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}, 0, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}, 0, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}, 0, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}, 0, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, FlagUp | FlagLoopback, true},
+ {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, 0, true},
}
// TestMulticastListener tests both single and double listen to a test
type TCPAddr struct {
IP IP
Port int
+ Zone string // IPv6 scoped addressing zone
}
// Network returns the address's network name, "tcp".
if err != nil {
return nil, err
}
- return &TCPAddr{ip, port}, nil
+ return &TCPAddr{IP: ip, Port: port}, nil
}
func sockaddrToTCP(sa syscall.Sockaddr) Addr {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
- return &TCPAddr{sa.Addr[0:], sa.Port}
+ return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port}
case *syscall.SockaddrInet6:
- return &TCPAddr{sa.Addr[0:], sa.Port}
+ return &TCPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
default:
if sa != nil {
// Diagnose when we will turn a non-nil sockaddr into a nil.
}
func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
- return ipToSockaddr(family, a.IP, a.Port)
+ return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
func (a *TCPAddr) toAddr() sockaddr {
type UDPAddr struct {
IP IP
Port int
+ Zone string // IPv6 scoped addressing zone
}
// Network returns the address's network name, "udp".
if err != nil {
return nil, err
}
- return &UDPAddr{ip, port}, nil
+ return &UDPAddr{IP: ip, Port: port}, nil
}
conn
}
-// UDP-specific methods.
-
// ReadFromUDP reads a UDP packet from c, copying the payload into b.
// It returns the number of bytes copied into b and the return address
// that was on the packet.
h, buf := unmarshalUDPHeader(buf)
n = copy(b, buf)
- return n, &UDPAddr{h.raddr, int(h.rport)}, nil
+ return n, &UDPAddr{IP: h.raddr, Port: int(h.rport)}, nil
}
// ReadFrom implements the PacketConn ReadFrom method.
// +build darwin freebsd linux netbsd openbsd windows
-// UDP sockets
+// UDP sockets for POSIX
package net
func sockaddrToUDP(sa syscall.Sockaddr) Addr {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
- return &UDPAddr{sa.Addr[0:], sa.Port}
+ return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
case *syscall.SockaddrInet6:
- return &UDPAddr{sa.Addr[0:], sa.Port}
+ return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
}
return nil
}
}
func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
- return ipToSockaddr(family, a.IP, a.Port)
+ return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
func (a *UDPAddr) toAddr() sockaddr {
func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
-// UDP-specific methods.
-
// ReadFromUDP reads a UDP packet from c, copying the payload into b.
// It returns the number of bytes copied into b and the return address
// that was on the packet.
n, sa, err := c.fd.ReadFrom(b)
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
- addr = &UDPAddr{sa.Addr[0:], sa.Port}
+ addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
case *syscall.SockaddrInet6:
- addr = &UDPAddr{sa.Addr[0:], sa.Port}
+ addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
}
return
}
if !c.ok() {
return 0, nil, syscall.EINVAL
}
- n, uaddr, err := c.ReadFromUDP(b)
- return n, uaddr.toAddr(), err
+ n, addr, err := c.ReadFromUDP(b)
+ return n, addr.toAddr(), err
}
// ReadMsgUDP reads a packet from c, copying the payload into b and
n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
- addr = &UDPAddr{sa.Addr[0:], sa.Port}
+ addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
case *syscall.SockaddrInet6:
- addr = &UDPAddr{sa.Addr[0:], sa.Port}
+ addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneToString(int(sa.ZoneId))}
}
return
}
func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
err := joinIPv4Group(c.fd, ifi, ip)
if err != nil {
- return &OpError{"joinipv4group", c.fd.net, &IPAddr{ip}, err}
+ return &OpError{"joinipv4group", c.fd.net, &IPAddr{IP: ip}, err}
}
return nil
}
func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
err := joinIPv6Group(c.fd, ifi, ip)
if err != nil {
- return &OpError{"joinipv6group", c.fd.net, &IPAddr{ip}, err}
+ return &OpError{"joinipv6group", c.fd.net, &IPAddr{IP: ip}, err}
}
return nil
}