Skip to content

Commit

Permalink
Don't auto-set broadcast unless subnet larger than /31
Browse files Browse the repository at this point in the history
Since [#248](#248), adding an address automatically sets the broadcast if the broadcast address was not specified. This is undesirable when adding an IP with a prefixlen of /31 or /32. (Additional details in the issues linked below.)

This changes the behavior so that the broadcast is only automatically set if the prefixlen is /30 or larger.

Issue reported in:

- #329
- #471

See also:

- [RFC 3021](http://tools.ietf.org/html/rfc3021)

Alternatives to this PR:

A. #472 - Adds `AddrAddWithoutCalculatedBroadcast`.
B. jjastrze-ovh@9a85a61 - Breaking change to make auto-setting the broadcast address an opt-in feature.
C. already works - Suppress setting the broadcast when addr's broadcast address is set to `0.0.0.0`. (This works today, but I'm not sure the behavior can be relied upon as a public API.)
  • Loading branch information
brandt authored and vishvananda committed Nov 13, 2019
1 parent e934999 commit aad0bae
Showing 1 changed file with 31 additions and 2 deletions.
33 changes: 31 additions & 2 deletions addr_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -108,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] | ^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))
Expand Down

0 comments on commit aad0bae

Please sign in to comment.