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) { ...@@ -22,18 +22,16 @@ func interfaceTable(ifindex int) ([]Interface, error) {
if err != nil { if err != nil {
return nil, os.NewSyscallError("route rib", err) return nil, os.NewSyscallError("route rib", err)
} }
msgs, err := syscall.ParseRoutingMessage(tab) msgs, err := syscall.ParseRoutingMessage(tab)
if err != nil { if err != nil {
return nil, os.NewSyscallError("route message", err) return nil, os.NewSyscallError("route message", err)
} }
var ift []Interface var ift []Interface
for _, m := range msgs { for _, m := range msgs {
switch v := m.(type) { switch m := m.(type) {
case *syscall.InterfaceMessage: case *syscall.InterfaceMessage:
if ifindex == 0 || ifindex == int(v.Header.Index) { if ifindex == 0 || ifindex == int(m.Header.Index) {
ifi, err := newLink(v) ifi, err := newLink(m)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -49,26 +47,25 @@ func newLink(m *syscall.InterfaceMessage) ([]Interface, error) { ...@@ -49,26 +47,25 @@ func newLink(m *syscall.InterfaceMessage) ([]Interface, error) {
if err != nil { if err != nil {
return nil, os.NewSyscallError("route sockaddr", err) return nil, os.NewSyscallError("route sockaddr", err)
} }
var ift []Interface var ift []Interface
for _, s := range sas { for _, sa := range sas {
switch v := s.(type) { switch sa := sa.(type) {
case *syscall.SockaddrDatalink: case *syscall.SockaddrDatalink:
// NOTE: SockaddrDatalink.Data is minimum work area, // NOTE: SockaddrDatalink.Data is minimum work area,
// can be larger. // 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)} ifi := Interface{Index: int(m.Header.Index), Flags: linkFlags(m.Header.Flags)}
var name [syscall.IFNAMSIZ]byte 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]) 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) ifi.MTU = int(m.Header.Data.Mtu)
addr := make([]byte, v.Alen) addr := make([]byte, sa.Alen)
for i := 0; i < int(v.Alen); i++ { for i := 0; i < int(sa.Alen); i++ {
addr[i] = byte(m.Data[int(v.Nlen)+i]) addr[i] = byte(m.Data[int(sa.Nlen)+i])
} }
ifi.HardwareAddr = addr[:v.Alen] ifi.HardwareAddr = addr[:sa.Alen]
ift = append(ift, ifi) ift = append(ift, ifi)
} }
} }
...@@ -103,18 +100,16 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) { ...@@ -103,18 +100,16 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
if err != nil { if err != nil {
return nil, os.NewSyscallError("route rib", err) return nil, os.NewSyscallError("route rib", err)
} }
msgs, err := syscall.ParseRoutingMessage(tab) msgs, err := syscall.ParseRoutingMessage(tab)
if err != nil { if err != nil {
return nil, os.NewSyscallError("route message", err) return nil, os.NewSyscallError("route message", err)
} }
var ifat []Addr var ifat []Addr
for _, m := range msgs { for _, m := range msgs {
switch v := m.(type) { switch m := m.(type) {
case *syscall.InterfaceAddrMessage: case *syscall.InterfaceAddrMessage:
if ifindex == 0 || ifindex == int(v.Header.Index) { if ifindex == 0 || ifindex == int(m.Header.Index) {
ifa, err := newAddr(v) ifa, err := newAddr(m)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -132,30 +127,29 @@ func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) { ...@@ -132,30 +127,29 @@ func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) {
if err != nil { if err != nil {
return nil, os.NewSyscallError("route sockaddr", err) return nil, os.NewSyscallError("route sockaddr", err)
} }
ifa := &IPNet{} ifa := &IPNet{}
for i, s := range sas { for i, sa := range sas {
switch v := s.(type) { switch sa := sa.(type) {
case *syscall.SockaddrInet4: case *syscall.SockaddrInet4:
switch i { switch i {
case 0: 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: 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: case *syscall.SockaddrInet6:
switch i { switch i {
case 0: case 0:
ifa.Mask = make(IPMask, IPv6len) ifa.Mask = make(IPMask, IPv6len)
copy(ifa.Mask, v.Addr[:]) copy(ifa.Mask, sa.Addr[:])
case 1: case 1:
ifa.IP = make(IP, IPv6len) ifa.IP = make(IP, IPv6len)
copy(ifa.IP, v.Addr[:]) copy(ifa.IP, sa.Addr[:])
// NOTE: KAME based IPv6 protcol stack usually embeds // NOTE: KAME based IPv6 protcol stack usually embeds
// the interface index in the interface-local or link- // the interface index in the interface-local or link-
// local address as the kernel-internal form. // local address as the kernel-internal form.
if ifa.IP.IsLinkLocalUnicast() { 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 ifa.IP[2], ifa.IP[3] = 0, 0
} }
} }
......
...@@ -19,18 +19,16 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { ...@@ -19,18 +19,16 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
if err != nil { if err != nil {
return nil, os.NewSyscallError("route rib", err) return nil, os.NewSyscallError("route rib", err)
} }
msgs, err := syscall.ParseRoutingMessage(tab) msgs, err := syscall.ParseRoutingMessage(tab)
if err != nil { if err != nil {
return nil, os.NewSyscallError("route message", err) return nil, os.NewSyscallError("route message", err)
} }
var ifmat []Addr var ifmat []Addr
for _, m := range msgs { for _, m := range msgs {
switch v := m.(type) { switch m := m.(type) {
case *syscall.InterfaceMulticastAddrMessage: case *syscall.InterfaceMulticastAddrMessage:
if ifindex == 0 || ifindex == int(v.Header.Index) { if ifindex == 0 || ifindex == int(m.Header.Index) {
ifma, err := newMulticastAddr(v) ifma, err := newMulticastAddr(m)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -46,22 +44,20 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) ...@@ -46,22 +44,20 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error)
if err != nil { if err != nil {
return nil, os.NewSyscallError("route sockaddr", err) return nil, os.NewSyscallError("route sockaddr", err)
} }
var ifmat []Addr var ifmat []Addr
for _, s := range sas { for _, sa := range sas {
switch v := s.(type) { switch sa := sa.(type) {
case *syscall.SockaddrInet4: 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()) ifmat = append(ifmat, ifma.toAddr())
case *syscall.SockaddrInet6: case *syscall.SockaddrInet6:
ifma := &IPAddr{IP: make(IP, IPv6len)} ifma := &IPAddr{IP: make(IP, IPv6len)}
copy(ifma.IP, v.Addr[:]) copy(ifma.IP, sa.Addr[:])
// NOTE: KAME based IPv6 protcol stack usually embeds // NOTE: KAME based IPv6 protcol stack usually embeds
// the interface index in the interface-local or link- // the interface index in the interface-local or link-
// local address as the kernel-internal form. // local address as the kernel-internal form.
if ifma.IP.IsInterfaceLocalMulticast() || if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
ifma.IP.IsLinkLocalMulticast() { ifma.Zone = zoneToString(int(ifma.IP[2]<<8 | ifma.IP[3]))
// remove embedded scope zone ID
ifma.IP[2], ifma.IP[3] = 0, 0 ifma.IP[2], ifma.IP[3] = 0, 0
} }
ifmat = append(ifmat, ifma.toAddr()) ifmat = append(ifmat, ifma.toAddr())
......
...@@ -19,18 +19,16 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { ...@@ -19,18 +19,16 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
if err != nil { if err != nil {
return nil, os.NewSyscallError("route rib", err) return nil, os.NewSyscallError("route rib", err)
} }
msgs, err := syscall.ParseRoutingMessage(tab) msgs, err := syscall.ParseRoutingMessage(tab)
if err != nil { if err != nil {
return nil, os.NewSyscallError("route message", err) return nil, os.NewSyscallError("route message", err)
} }
var ifmat []Addr var ifmat []Addr
for _, m := range msgs { for _, m := range msgs {
switch v := m.(type) { switch m := m.(type) {
case *syscall.InterfaceMulticastAddrMessage: case *syscall.InterfaceMulticastAddrMessage:
if ifindex == 0 || ifindex == int(v.Header.Index) { if ifindex == 0 || ifindex == int(m.Header.Index) {
ifma, err := newMulticastAddr(v) ifma, err := newMulticastAddr(m)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -46,22 +44,20 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) ...@@ -46,22 +44,20 @@ func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error)
if err != nil { if err != nil {
return nil, os.NewSyscallError("route sockaddr", err) return nil, os.NewSyscallError("route sockaddr", err)
} }
var ifmat []Addr var ifmat []Addr
for _, s := range sas { for _, sa := range sas {
switch v := s.(type) { switch sa := sa.(type) {
case *syscall.SockaddrInet4: 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()) ifmat = append(ifmat, ifma.toAddr())
case *syscall.SockaddrInet6: case *syscall.SockaddrInet6:
ifma := &IPAddr{IP: make(IP, IPv6len)} ifma := &IPAddr{IP: make(IP, IPv6len)}
copy(ifma.IP, v.Addr[:]) copy(ifma.IP, sa.Addr[:])
// NOTE: KAME based IPv6 protcol stack usually embeds // NOTE: KAME based IPv6 protcol stack usually embeds
// the interface index in the interface-local or link- // the interface index in the interface-local or link-
// local address as the kernel-internal form. // local address as the kernel-internal form.
if ifma.IP.IsInterfaceLocalMulticast() || if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
ifma.IP.IsLinkLocalMulticast() { ifma.Zone = zoneToString(int(ifma.IP[2]<<8 | ifma.IP[3]))
// remove embedded scope zone ID
ifma.IP[2], ifma.IP[3] = 0, 0 ifma.IP[2], ifma.IP[3] = 0, 0
} }
ifmat = append(ifmat, ifma.toAddr()) ifmat = append(ifmat, ifma.toAddr())
......
...@@ -20,17 +20,16 @@ func interfaceTable(ifindex int) ([]Interface, error) { ...@@ -20,17 +20,16 @@ func interfaceTable(ifindex int) ([]Interface, error) {
if err != nil { if err != nil {
return nil, os.NewSyscallError("netlink rib", err) return nil, os.NewSyscallError("netlink rib", err)
} }
msgs, err := syscall.ParseNetlinkMessage(tab) msgs, err := syscall.ParseNetlinkMessage(tab)
if err != nil { if err != nil {
return nil, os.NewSyscallError("netlink message", err) return nil, os.NewSyscallError("netlink message", err)
} }
var ift []Interface var ift []Interface
loop:
for _, m := range msgs { for _, m := range msgs {
switch m.Header.Type { switch m.Header.Type {
case syscall.NLMSG_DONE: case syscall.NLMSG_DONE:
goto done break loop
case syscall.RTM_NEWLINK: case syscall.RTM_NEWLINK:
ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0])) ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
if ifindex == 0 || ifindex == int(ifim.Index) { if ifindex == 0 || ifindex == int(ifim.Index) {
...@@ -43,7 +42,6 @@ func interfaceTable(ifindex int) ([]Interface, error) { ...@@ -43,7 +42,6 @@ func interfaceTable(ifindex int) ([]Interface, error) {
} }
} }
} }
done:
return ift, nil return ift, nil
} }
...@@ -98,12 +96,10 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) { ...@@ -98,12 +96,10 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
if err != nil { if err != nil {
return nil, os.NewSyscallError("netlink rib", err) return nil, os.NewSyscallError("netlink rib", err)
} }
msgs, err := syscall.ParseNetlinkMessage(tab) msgs, err := syscall.ParseNetlinkMessage(tab)
if err != nil { if err != nil {
return nil, os.NewSyscallError("netlink message", err) return nil, os.NewSyscallError("netlink message", err)
} }
ifat, err := addrTable(msgs, ifindex) ifat, err := addrTable(msgs, ifindex)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -113,10 +109,11 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) { ...@@ -113,10 +109,11 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) { func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) {
var ifat []Addr var ifat []Addr
loop:
for _, m := range msgs { for _, m := range msgs {
switch m.Header.Type { switch m.Header.Type {
case syscall.NLMSG_DONE: case syscall.NLMSG_DONE:
goto done break loop
case syscall.RTM_NEWADDR: case syscall.RTM_NEWADDR:
ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0])) ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
ifi, err := InterfaceByIndex(int(ifam.Index)) ifi, err := InterfaceByIndex(int(ifam.Index))
...@@ -132,7 +129,6 @@ func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) { ...@@ -132,7 +129,6 @@ func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) {
} }
} }
} }
done:
return ifat, nil return ifat, nil
} }
...@@ -149,6 +145,9 @@ func newAddr(attrs []syscall.NetlinkRouteAttr, ifi *Interface, ifam *syscall.IfA ...@@ -149,6 +145,9 @@ func newAddr(attrs []syscall.NetlinkRouteAttr, ifi *Interface, ifam *syscall.IfA
ifa.IP = make(IP, IPv6len) ifa.IP = make(IP, IPv6len)
copy(ifa.IP, a.Value[:]) copy(ifa.IP, a.Value[:])
ifa.Mask = CIDRMask(int(ifam.Prefixlen), 8*IPv6len) 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 { ...@@ -180,7 +179,6 @@ func parseProcNetIGMP(path string, ifi *Interface) []Addr {
return nil return nil
} }
defer fd.close() defer fd.close()
var ( var (
ifmat []Addr ifmat []Addr
name string name string
...@@ -218,7 +216,6 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr { ...@@ -218,7 +216,6 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
return nil return nil
} }
defer fd.close() defer fd.close()
var ifmat []Addr var ifmat []Addr
b := make([]byte, IPv6len) b := make([]byte, IPv6len)
for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
...@@ -231,6 +228,9 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr { ...@@ -231,6 +228,9 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
b[i/2], _ = xtoi2(f[2][i:i+2], 0) 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]}} 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()) ifmat = append(ifmat, ifma.toAddr())
} }
} }
......
...@@ -10,5 +10,6 @@ package net ...@@ -10,5 +10,6 @@ package net
// addresses for all network interfaces. Otherwise it returns // addresses for all network interfaces. Otherwise it returns
// addresses for a specific interface. // addresses for a specific interface.
func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
// TODO(mikio): Implement this like other platforms.
return nil, nil return nil, nil
} }
...@@ -10,5 +10,6 @@ package net ...@@ -10,5 +10,6 @@ package net
// addresses for all network interfaces. Otherwise it returns // addresses for all network interfaces. Otherwise it returns
// addresses for a specific interface. // addresses for a specific interface.
func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
// TODO(mikio): Implement this like other platforms.
return nil, nil return nil, nil
} }
...@@ -25,6 +25,9 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) { ...@@ -25,6 +25,9 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) {
b := make([]byte, 1000) b := make([]byte, 1000)
l := uint32(len(b)) l := uint32(len(b))
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0])) 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) err := syscall.GetAdaptersInfo(a, &l)
if err == syscall.ERROR_BUFFER_OVERFLOW { if err == syscall.ERROR_BUFFER_OVERFLOW {
b = make([]byte, l) b = make([]byte, l)
...@@ -154,5 +157,6 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) { ...@@ -154,5 +157,6 @@ func interfaceAddrTable(ifindex int) ([]Addr, error) {
// addresses for all network interfaces. Otherwise it returns // addresses for all network interfaces. Otherwise it returns
// addresses for a specific interface. // addresses for a specific interface.
func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
// TODO(mikio): Implement this like other platforms.
return nil, nil 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