net: set up IPv6 scoped addressing zone for network facilities

This CL changes nothing to existing API behavior, just sets up
Zone in IPNet and IPAddr structures if possible.

Also does small simplification.

Update #4234.

R=rsc, dave
CC=golang-dev
https://golang.org/cl/7300081
This commit is contained in:
Mikio Hara 2013-02-20 08:18:04 +09:00
parent e4890e57e1
commit 40c2fbf4f2
7 changed files with 56 additions and 64 deletions

View File

@ -22,18 +22,16 @@ func interfaceTable(ifindex int) ([]Interface, error) {
if err != nil {
return nil, os.NewSyscallError("route rib", err)
}
msgs, err := syscall.ParseRoutingMessage(tab)
if err != nil {
return nil, os.NewSyscallError("route message", err)
}
var ift []Interface
for _, m := range msgs {
switch v := m.(type) {
switch m := m.(type) {
case *syscall.InterfaceMessage:
if ifindex == 0 || ifindex == int(v.Header.Index) {
ifi, err := newLink(v)
if ifindex == 0 || ifindex == int(m.Header.Index) {
ifi, err := newLink(m)
if err != nil {
return nil, err
}
@ -49,26 +47,25 @@ func newLink(m *syscall.InterfaceMessage) ([]Interface, error) {
if err != nil {
return nil, os.NewSyscallError("route sockaddr", err)
}
var ift []Interface
for _, s := range sas {
switch v := s.(type) {
for _, sa := range sas {
switch sa := sa.(type) {
case *syscall.SockaddrDatalink:
// NOTE: SockaddrDatalink.Data is minimum work area,
// can be larger.
m.Data = m.Data[unsafe.Offsetof(v.Data):]
m.Data = m.Data[unsafe.Offsetof(sa.Data):]
ifi := Interface{Index: int(m.Header.Index), Flags: linkFlags(m.Header.Flags)}
var name [syscall.IFNAMSIZ]byte
for i := 0; i < int(v.Nlen); i++ {
for i := 0; i < int(sa.Nlen); i++ {
name[i] = byte(m.Data[i])
}
ifi.Name = string(name[:v.Nlen])
ifi.Name = string(name[:sa.Nlen])
ifi.MTU = int(m.Header.Data.Mtu)
addr := make([]byte, v.Alen)
for i := 0; i < int(v.Alen); i++ {
addr[i] = byte(m.Data[int(v.Nlen)+i])
addr := make([]byte, sa.Alen)
for i := 0; i < int(sa.Alen); i++ {
addr[i] = byte(m.Data[int(sa.Nlen)+i])
}
ifi.HardwareAddr = addr[:v.Alen]
ifi.HardwareAddr = addr[:sa.Alen]
ift = append(ift, ifi)
}
}
@ -103,18 +100,16 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
if err != nil {
return nil, os.NewSyscallError("route rib", err)
}
msgs, err := syscall.ParseRoutingMessage(tab)
if err != nil {
return nil, os.NewSyscallError("route message", err)
}
var ifat []Addr
for _, m := range msgs {
switch v := m.(type) {
switch m := m.(type) {
case *syscall.InterfaceAddrMessage:
if ifindex == 0 || ifindex == int(v.Header.Index) {
ifa, err := newAddr(v)
if ifindex == 0 || ifindex == int(m.Header.Index) {
ifa, err := newAddr(m)
if err != nil {
return nil, err
}
@ -132,30 +127,29 @@ func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) {
if err != nil {
return nil, os.NewSyscallError("route sockaddr", err)
}
ifa := &IPNet{}
for i, s := range sas {
switch v := s.(type) {
for i, sa := range sas {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
switch i {
case 0:
ifa.Mask = IPv4Mask(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
ifa.Mask = IPv4Mask(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
case 1:
ifa.IP = IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
ifa.IP = IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
}
case *syscall.SockaddrInet6:
switch i {
case 0:
ifa.Mask = make(IPMask, IPv6len)
copy(ifa.Mask, v.Addr[:])
copy(ifa.Mask, sa.Addr[:])
case 1:
ifa.IP = make(IP, IPv6len)
copy(ifa.IP, v.Addr[:])
copy(ifa.IP, sa.Addr[:])
// NOTE: KAME based IPv6 protcol stack usually embeds
// the interface index in the interface-local or link-
// local address as the kernel-internal form.
if ifa.IP.IsLinkLocalUnicast() {
// remove embedded scope zone ID
ifa.Zone = zoneToString(int(ifa.IP[2]<<8 | ifa.IP[3]))
ifa.IP[2], ifa.IP[3] = 0, 0
}
}

View File

@ -19,18 +19,16 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
if err != nil {
return nil, os.NewSyscallError("route rib", err)
}
msgs, err := syscall.ParseRoutingMessage(tab)
if err != nil {
return nil, os.NewSyscallError("route message", err)
}
var ifmat []Addr
for _, m := range msgs {
switch v := m.(type) {
switch m := m.(type) {
case *syscall.InterfaceMulticastAddrMessage:
if ifindex == 0 || ifindex == int(v.Header.Index) {
ifma, err := newMulticastAddr(v)
if ifindex == 0 || ifindex == int(m.Header.Index) {
ifma, err := newMulticastAddr(m)
if err != nil {
return nil, err
}
@ -46,22 +44,20 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error)
if err != nil {
return nil, os.NewSyscallError("route sockaddr", err)
}
var ifmat []Addr
for _, s := range sas {
switch v := s.(type) {
for _, sa := range sas {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
ifma := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
ifma := &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])}
ifmat = append(ifmat, ifma.toAddr())
case *syscall.SockaddrInet6:
ifma := &IPAddr{IP: make(IP, IPv6len)}
copy(ifma.IP, v.Addr[:])
copy(ifma.IP, sa.Addr[:])
// NOTE: KAME based IPv6 protcol stack usually embeds
// the interface index in the interface-local or link-
// local address as the kernel-internal form.
if ifma.IP.IsInterfaceLocalMulticast() ||
ifma.IP.IsLinkLocalMulticast() {
// remove embedded scope zone ID
if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
ifma.Zone = zoneToString(int(ifma.IP[2]<<8 | ifma.IP[3]))
ifma.IP[2], ifma.IP[3] = 0, 0
}
ifmat = append(ifmat, ifma.toAddr())

View File

@ -19,18 +19,16 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
if err != nil {
return nil, os.NewSyscallError("route rib", err)
}
msgs, err := syscall.ParseRoutingMessage(tab)
if err != nil {
return nil, os.NewSyscallError("route message", err)
}
var ifmat []Addr
for _, m := range msgs {
switch v := m.(type) {
switch m := m.(type) {
case *syscall.InterfaceMulticastAddrMessage:
if ifindex == 0 || ifindex == int(v.Header.Index) {
ifma, err := newMulticastAddr(v)
if ifindex == 0 || ifindex == int(m.Header.Index) {
ifma, err := newMulticastAddr(m)
if err != nil {
return nil, err
}
@ -46,22 +44,20 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error)
if err != nil {
return nil, os.NewSyscallError("route sockaddr", err)
}
var ifmat []Addr
for _, s := range sas {
switch v := s.(type) {
for _, sa := range sas {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
ifma := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
ifma := &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])}
ifmat = append(ifmat, ifma.toAddr())
case *syscall.SockaddrInet6:
ifma := &IPAddr{IP: make(IP, IPv6len)}
copy(ifma.IP, v.Addr[:])
copy(ifma.IP, sa.Addr[:])
// NOTE: KAME based IPv6 protcol stack usually embeds
// the interface index in the interface-local or link-
// local address as the kernel-internal form.
if ifma.IP.IsInterfaceLocalMulticast() ||
ifma.IP.IsLinkLocalMulticast() {
// remove embedded scope zone ID
if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
ifma.Zone = zoneToString(int(ifma.IP[2]<<8 | ifma.IP[3]))
ifma.IP[2], ifma.IP[3] = 0, 0
}
ifmat = append(ifmat, ifma.toAddr())

View File

@ -20,17 +20,16 @@ func interfaceTable(ifindex int) ([]Interface, error) {
if err != nil {
return nil, os.NewSyscallError("netlink rib", err)
}
msgs, err := syscall.ParseNetlinkMessage(tab)
if err != nil {
return nil, os.NewSyscallError("netlink message", err)
}
var ift []Interface
loop:
for _, m := range msgs {
switch m.Header.Type {
case syscall.NLMSG_DONE:
goto done
break loop
case syscall.RTM_NEWLINK:
ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
if ifindex == 0 || ifindex == int(ifim.Index) {
@ -43,7 +42,6 @@ func interfaceTable(ifindex int) ([]Interface, error) {
}
}
}
done:
return ift, nil
}
@ -98,12 +96,10 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
if err != nil {
return nil, os.NewSyscallError("netlink rib", err)
}
msgs, err := syscall.ParseNetlinkMessage(tab)
if err != nil {
return nil, os.NewSyscallError("netlink message", err)
}
ifat, err := addrTable(msgs, ifindex)
if err != nil {
return nil, err
@ -113,10 +109,11 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) {
var ifat []Addr
loop:
for _, m := range msgs {
switch m.Header.Type {
case syscall.NLMSG_DONE:
goto done
break loop
case syscall.RTM_NEWADDR:
ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
ifi, err := InterfaceByIndex(int(ifam.Index))
@ -132,7 +129,6 @@ func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) {
}
}
}
done:
return ifat, nil
}
@ -149,6 +145,9 @@ func newAddr(attrs []syscall.NetlinkRouteAttr, ifi *Interface, ifam *syscall.IfA
ifa.IP = make(IP, IPv6len)
copy(ifa.IP, a.Value[:])
ifa.Mask = CIDRMask(int(ifam.Prefixlen), 8*IPv6len)
if ifam.Scope == syscall.RT_SCOPE_HOST || ifam.Scope == syscall.RT_SCOPE_LINK {
ifa.Zone = zoneToString(int(ifam.Index))
}
}
}
}
@ -180,7 +179,6 @@ func parseProcNetIGMP(path string, ifi *Interface) []Addr {
return nil
}
defer fd.close()
var (
ifmat []Addr
name string
@ -218,7 +216,6 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
return nil
}
defer fd.close()
var ifmat []Addr
b := make([]byte, IPv6len)
for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
@ -231,6 +228,9 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
b[i/2], _ = xtoi2(f[2][i:i+2], 0)
}
ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}}
if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
ifma.Zone = ifi.Name
}
ifmat = append(ifmat, ifma.toAddr())
}
}

View File

@ -10,5 +10,6 @@ package net
// addresses for all network interfaces. Otherwise it returns
// addresses for a specific interface.
func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
// TODO(mikio): Implement this like other platforms.
return nil, nil
}

View File

@ -10,5 +10,6 @@ package net
// addresses for all network interfaces. Otherwise it returns
// addresses for a specific interface.
func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
// TODO(mikio): Implement this like other platforms.
return nil, nil
}

View File

@ -25,6 +25,9 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) {
b := make([]byte, 1000)
l := uint32(len(b))
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
// TODO(mikio): GetAdaptersInfo returns IP_ADAPTER_INFO that
// contains IPv4 address list only. We should use another API
// for fetching IPv6 stuff from the kernel.
err := syscall.GetAdaptersInfo(a, &l)
if err == syscall.ERROR_BUFFER_OVERFLOW {
b = make([]byte, l)
@ -154,5 +157,6 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
// addresses for all network interfaces. Otherwise it returns
// addresses for a specific interface.
func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
// TODO(mikio): Implement this like other platforms.
return nil, nil
}