Commit 8c0a52f2 authored by Mikio Hara's avatar Mikio Hara

net: handle IP interface stack correctly on linux

A configuration like the following:

7: tun6rd: <NOARP,UP,LOWER_UP> mtu 1280
        link/sit 10.11.12.13 brd 0.0.0.0
        inet 1.2.3.4/24 scope global tun6rd
        inet6 2014:1001:a0b:c0d::1/32 scope global
        inet6 ::10.11.12.13/128 scope global
9: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1496
        link/ppp
        inet 192.168.101.234 peer 192.168.102.234/32 scope global ppp0
        inet 10.20.30.40/24 scope global ppp0
        inet6 2014:1002::1/64 scope global
11: tun0@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480
        link/ipip 192.168.202.34 peer 192.168.202.69
        inet 192.168.10.1/24 scope global tunnel0
        inet6 2014:1003::1/64 scope global

will be handled like below.

"tun6rd": flags "up", ifindex 7, mtu 1280
        hardware address ""
        interface address "1.2.3.4/24"
        interface address "2014:1001:a0b:c0d::1/32"
        interface address "::a0b:c0d/128"
"ppp0": flags "up|pointtopoint|multicast", ifindex 9, mtu 1496
        hardware address ""
        interface address "192.168.101.234/32"
        interface address "10.20.30.40/24"
        interface address "2014:1002::1/64"
"tun0": flags "up|pointtopoint", ifindex 11, mtu 1480
        hardware address ""
        interface address "192.168.10.1/24"
        interface address "2014:1003::1/64"

Fixes #6433.
Update #4839

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/57700043
parent be9c514f
......@@ -45,15 +45,41 @@ loop:
return ift, nil
}
const (
// See linux/if_arp.h.
// Note that Linux doesn't support IPv4 over IPv6 tunneling.
sysARPHardwareIPv4IPv4 = 768 // IPv4 over IPv4 tunneling
sysARPHardwareIPv6IPv6 = 769 // IPv6 over IPv6 tunneling
sysARPHardwareIPv6IPv4 = 776 // IPv6 over IPv4 tunneling
sysARPHardwareGREIPv4 = 778 // any over GRE over IPv4 tunneling
sysARPHardwareGREIPv6 = 823 // any over GRE over IPv6 tunneling
)
func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) *Interface {
ifi := &Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)}
for _, a := range attrs {
switch a.Attr.Type {
case syscall.IFLA_ADDRESS:
// We never return any /32 or /128 IP address
// prefix on any IP tunnel interface as the
// hardware address.
switch len(a.Value) {
case IPv4len:
switch ifim.Type {
case sysARPHardwareIPv4IPv4, sysARPHardwareGREIPv4, sysARPHardwareIPv6IPv4:
continue
}
case IPv6len:
switch ifim.Type {
case sysARPHardwareIPv6IPv6, sysARPHardwareGREIPv6:
continue
}
}
var nonzero bool
for _, b := range a.Value {
if b != 0 {
nonzero = true
break
}
}
if nonzero {
......@@ -147,19 +173,31 @@ loop:
}
func newAddr(ifi *Interface, ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRouteAttr) Addr {
for _, a := range attrs {
if ifi.Flags&FlagPointToPoint != 0 && a.Attr.Type == syscall.IFA_LOCAL ||
ifi.Flags&FlagPointToPoint == 0 && a.Attr.Type == syscall.IFA_ADDRESS {
switch ifam.Family {
case syscall.AF_INET:
return &IPNet{IP: IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3]), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv4len)}
case syscall.AF_INET6:
ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv6len)}
copy(ifa.IP, a.Value[:])
return ifa
var ipPointToPoint bool
// Seems like we need to make sure whether the IP interface
// stack consists of IP point-to-point numbered or unnumbered
// addressing over point-to-point link encapsulation.
if ifi.Flags&FlagPointToPoint != 0 {
for _, a := range attrs {
if a.Attr.Type == syscall.IFA_LOCAL {
ipPointToPoint = true
break
}
}
}
for _, a := range attrs {
if ipPointToPoint && a.Attr.Type == syscall.IFA_ADDRESS || !ipPointToPoint && a.Attr.Type == syscall.IFA_LOCAL {
continue
}
switch ifam.Family {
case syscall.AF_INET:
return &IPNet{IP: IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3]), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv4len)}
case syscall.AF_INET6:
ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv6len)}
copy(ifa.IP, a.Value[:])
return ifa
}
}
return 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