summaryrefslogtreecommitdiff
path: root/vendor/github.com/vishvananda/netlink/addr_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/vishvananda/netlink/addr_linux.go')
-rw-r--r--vendor/github.com/vishvananda/netlink/addr_linux.go105
1 files changed, 84 insertions, 21 deletions
diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go
index d59c3281e..28746d5af 100644
--- a/vendor/github.com/vishvananda/netlink/addr_linux.go
+++ b/vendor/github.com/vishvananda/netlink/addr_linux.go
@@ -15,39 +15,62 @@ import (
const IFA_FLAGS = 0x8
// AddrAdd will add an IP address to a link device.
+//
// Equivalent to: `ip addr add $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func AddrAdd(link Link, addr *Addr) error {
return pkgHandle.AddrAdd(link, addr)
}
// AddrAdd will add an IP address to a link device.
+//
// Equivalent to: `ip addr add $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func (h *Handle) AddrAdd(link Link, addr *Addr) error {
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
return h.addrHandle(link, addr, req)
}
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
+//
// Equivalent to: `ip addr replace $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func AddrReplace(link Link, addr *Addr) error {
return pkgHandle.AddrReplace(link, addr)
}
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
+//
// Equivalent to: `ip addr replace $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func (h *Handle) AddrReplace(link Link, addr *Addr) error {
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK)
return h.addrHandle(link, addr, req)
}
// AddrDel will delete an IP address from a link device.
+//
// Equivalent to: `ip addr del $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func AddrDel(link Link, addr *Addr) error {
return pkgHandle.AddrDel(link, addr)
}
// AddrDel will delete an IP address from a link device.
// Equivalent to: `ip addr del $addr dev $link`
+//
+// If `addr` is an IPv4 address and the broadcast address is not given, it
+// will be automatically computed based on the IP mask if /30 or larger.
func (h *Handle) AddrDel(link Link, addr *Addr) error {
req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK)
return h.addrHandle(link, addr, req)
@@ -65,7 +88,11 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
msg := nl.NewIfAddrmsg(family)
msg.Index = uint32(base.Index)
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)
req.AddData(msg)
@@ -104,14 +131,20 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
}
if family == FAMILY_V4 {
- if addr.Broadcast == nil {
+ // Automatically set the broadcast address if it is unset and the
+ // subnet is large enough to sensibly have one (/30 or larger).
+ // See: RFC 3021
+ if addr.Broadcast == nil && prefixlen < 31 {
calcBroadcast := make(net.IP, masklen/8)
for i := range localAddrData {
- calcBroadcast[i] = localAddrData[i] | ^addr.Mask[i]
+ calcBroadcast[i] = localAddrData[i] | ^mask[i]
}
addr.Broadcast = calcBroadcast
}
- req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
+
+ if addr.Broadcast != nil {
+ req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
+ }
if addr.Label != "" {
labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label))
@@ -206,13 +239,17 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
IP: attr.Value,
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
}
- addr.Peer = dst
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{
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:
addr.Broadcast = attr.Value
case unix.IFA_LABEL:
@@ -226,12 +263,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 {
- addr.IPNet = local
+ if family == FAMILY_V4 && local.IP.Equal(dst.IP) {
+ addr.IPNet = dst
+ } else {
+ addr.IPNet = local
+ addr.Peer = dst
+ }
} else {
addr.IPNet = dst
}
+
addr.Scope = int(msg.Scope)
return
@@ -250,21 +299,22 @@ type AddrUpdate struct {
// AddrSubscribe takes a chan down which notifications will be sent
// when addresses change. Close the 'done' chan to stop subscription.
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
- return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
+ return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0)
}
// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
// to choose the network namespace in which to subscribe (ns).
func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
- return addrSubscribeAt(ns, netns.None(), ch, done, nil, false)
+ return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0)
}
// AddrSubscribeOptions contains a set of options to use with
// AddrSubscribeWithOptions.
type AddrSubscribeOptions struct {
- Namespace *netns.NsHandle
- ErrorCallback func(error)
- ListExisting bool
+ Namespace *netns.NsHandle
+ ErrorCallback func(error)
+ ListExisting bool
+ ReceiveBufferSize int
}
// AddrSubscribeWithOptions work like AddrSubscribe but enable to
@@ -275,10 +325,10 @@ func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, option
none := netns.None()
options.Namespace = &none
}
- return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
+ return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize)
}
-func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
+func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int) error {
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR)
if err != nil {
return err
@@ -289,6 +339,12 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
s.Close()
}()
}
+ if rcvbuf != 0 {
+ err = pkgHandle.SetSocketReceiveBufferSize(rcvbuf, false)
+ if err != nil {
+ return err
+ }
+ }
if listExisting {
req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR,
unix.NLM_F_DUMP)
@@ -301,13 +357,19 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
go func() {
defer close(ch)
for {
- msgs, err := s.Receive()
+ msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
cberr(err)
}
return
}
+ if from.Pid != nl.PidKernel {
+ if cberr != nil {
+ cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
+ }
+ continue
+ }
for _, m := range msgs {
if m.Header.Type == unix.NLMSG_DONE {
continue
@@ -319,16 +381,17 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
continue
}
if cberr != nil {
- cberr(syscall.Errno(-error))
+ cberr(fmt.Errorf("error message: %v",
+ syscall.Errno(-error)))
}
- return
+ continue
}
msgType := m.Header.Type
if msgType != unix.RTM_NEWADDR && msgType != unix.RTM_DELADDR {
if cberr != nil {
cberr(fmt.Errorf("bad message type: %d", msgType))
}
- return
+ continue
}
addr, _, ifindex, err := parseAddr(m.Data)
@@ -336,7 +399,7 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
if cberr != nil {
cberr(fmt.Errorf("could not parse address: %v", err))
}
- return
+ continue
}
ch <- AddrUpdate{LinkAddress: *addr.IPNet,