Commit 40c2fbf4 authored by Mikio Hara's avatar Mikio Hara

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
parent e4890e57
......@@ -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
}
}
......
......@@ -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())
......
......@@ -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())
......
......@@ -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())
}
}
......
......@@ -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
}
......@@ -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
}
......@@ -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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment