mirror of
https://github.com/vishvananda/netlink.git
synced 2025-09-27 04:05:59 +08:00
fix prefixlen/local IP, incl. PtP addresses
From libnl addr.c comment: IPv6 sends the local address as IFA_ADDRESS with no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS with IFA_ADDRESS being the peer address if they differ But obviously, IPv6 sends IFA_LOCAL in case of PtP. From iproute2 manual: If a peer address is specified, the local address cannot have a prefix length. The network prefix is associated with the peer rather than with the local address.
This commit is contained in:

committed by
Vish (Ishaya) Abrams

parent
7c0b5944a3
commit
b1cc70dea2
@@ -65,7 +65,11 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
|||||||
msg := nl.NewIfAddrmsg(family)
|
msg := nl.NewIfAddrmsg(family)
|
||||||
msg.Index = uint32(base.Index)
|
msg.Index = uint32(base.Index)
|
||||||
msg.Scope = uint8(addr.Scope)
|
msg.Scope = uint8(addr.Scope)
|
||||||
prefixlen, masklen := addr.Mask.Size()
|
mask := addr.Mask
|
||||||
|
if addr.Peer != nil {
|
||||||
|
mask = addr.Peer.Mask
|
||||||
|
}
|
||||||
|
prefixlen, masklen := mask.Size()
|
||||||
msg.Prefixlen = uint8(prefixlen)
|
msg.Prefixlen = uint8(prefixlen)
|
||||||
req.AddData(msg)
|
req.AddData(msg)
|
||||||
|
|
||||||
@@ -107,7 +111,7 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
|
|||||||
if addr.Broadcast == nil {
|
if addr.Broadcast == nil {
|
||||||
calcBroadcast := make(net.IP, masklen/8)
|
calcBroadcast := make(net.IP, masklen/8)
|
||||||
for i := range localAddrData {
|
for i := range localAddrData {
|
||||||
calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i]
|
calcBroadcast[i] = localAddrData[i] | ^mask[i]
|
||||||
}
|
}
|
||||||
addr.Broadcast = calcBroadcast
|
addr.Broadcast = calcBroadcast
|
||||||
}
|
}
|
||||||
@@ -206,13 +210,17 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
|
|||||||
IP: attr.Value,
|
IP: attr.Value,
|
||||||
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
||||||
}
|
}
|
||||||
addr.Peer = dst
|
|
||||||
case unix.IFA_LOCAL:
|
case unix.IFA_LOCAL:
|
||||||
|
// iproute2 manual:
|
||||||
|
// If a peer address is specified, the local address
|
||||||
|
// cannot have a prefix length. The network prefix is
|
||||||
|
// associated with the peer rather than with the local
|
||||||
|
// address.
|
||||||
|
n := 8 * len(attr.Value)
|
||||||
local = &net.IPNet{
|
local = &net.IPNet{
|
||||||
IP: attr.Value,
|
IP: attr.Value,
|
||||||
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
|
Mask: net.CIDRMask(n, n),
|
||||||
}
|
}
|
||||||
addr.IPNet = local
|
|
||||||
case unix.IFA_BROADCAST:
|
case unix.IFA_BROADCAST:
|
||||||
addr.Broadcast = attr.Value
|
addr.Broadcast = attr.Value
|
||||||
case unix.IFA_LABEL:
|
case unix.IFA_LABEL:
|
||||||
@@ -226,12 +234,24 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS
|
// libnl addr.c comment:
|
||||||
|
// IPv6 sends the local address as IFA_ADDRESS with no
|
||||||
|
// IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS
|
||||||
|
// with IFA_ADDRESS being the peer address if they differ
|
||||||
|
//
|
||||||
|
// But obviously, as there are IPv6 PtP addresses, too,
|
||||||
|
// IFA_LOCAL should also be handled for IPv6.
|
||||||
if local != nil {
|
if local != nil {
|
||||||
addr.IPNet = local
|
if family == FAMILY_V4 && local.IP.Equal(dst.IP) {
|
||||||
|
addr.IPNet = dst
|
||||||
|
} else {
|
||||||
|
addr.IPNet = local
|
||||||
|
addr.Peer = dst
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
addr.IPNet = dst
|
addr.IPNet = dst
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.Scope = int(msg.Scope)
|
addr.Scope = int(msg.Scope)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@@ -24,7 +24,7 @@ func DoTestAddr(t *testing.T, FunctionUndertest func(Link, *Addr) error) {
|
|||||||
t.Skipf("Fails in travis with: addr_test.go:68: Address flags not set properly, got=0, expected=128")
|
t.Skipf("Fails in travis with: addr_test.go:68: Address flags not set properly, got=0, expected=128")
|
||||||
}
|
}
|
||||||
// TODO: IFA_F_PERMANENT does not seem to be set by default on older kernels?
|
// TODO: IFA_F_PERMANENT does not seem to be set by default on older kernels?
|
||||||
var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(24, 32)}
|
var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(32, 32)}
|
||||||
var peer = &net.IPNet{IP: net.IPv4(127, 0, 0, 3), Mask: net.CIDRMask(24, 32)}
|
var peer = &net.IPNet{IP: net.IPv4(127, 0, 0, 3), Mask: net.CIDRMask(24, 32)}
|
||||||
var addrTests = []struct {
|
var addrTests = []struct {
|
||||||
addr *Addr
|
addr *Addr
|
||||||
|
Reference in New Issue
Block a user