Skip to content

Commit 727e5f2

Browse files
committed
Don't auto-set broadcast unless subnet larger than /31
Since [vishvananda#248](vishvananda#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: - vishvananda#329 - vishvananda#471 See also: - [RFC 3021](http://tools.ietf.org/html/rfc3021) Alternatives to this PR: A. vishvananda#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.)
1 parent 2ec5bdc commit 727e5f2

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

addr_linux.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,62 @@ import (
1515
const IFA_FLAGS = 0x8
1616

1717
// AddrAdd will add an IP address to a link device.
18+
//
1819
// Equivalent to: `ip addr add $addr dev $link`
20+
//
21+
// If `addr` is an IPv4 address and the broadcast address is not given, it
22+
// will be automatically computed based on the IP mask if /30 or larger.
1923
func AddrAdd(link Link, addr *Addr) error {
2024
return pkgHandle.AddrAdd(link, addr)
2125
}
2226

2327
// AddrAdd will add an IP address to a link device.
28+
//
2429
// Equivalent to: `ip addr add $addr dev $link`
30+
//
31+
// If `addr` is an IPv4 address and the broadcast address is not given, it
32+
// will be automatically computed based on the IP mask if /30 or larger.
2533
func (h *Handle) AddrAdd(link Link, addr *Addr) error {
2634
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
2735
return h.addrHandle(link, addr, req)
2836
}
2937

3038
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
39+
//
3140
// Equivalent to: `ip addr replace $addr dev $link`
41+
//
42+
// If `addr` is an IPv4 address and the broadcast address is not given, it
43+
// will be automatically computed based on the IP mask if /30 or larger.
3244
func AddrReplace(link Link, addr *Addr) error {
3345
return pkgHandle.AddrReplace(link, addr)
3446
}
3547

3648
// AddrReplace will replace (or, if not present, add) an IP address on a link device.
49+
//
3750
// Equivalent to: `ip addr replace $addr dev $link`
51+
//
52+
// If `addr` is an IPv4 address and the broadcast address is not given, it
53+
// will be automatically computed based on the IP mask if /30 or larger.
3854
func (h *Handle) AddrReplace(link Link, addr *Addr) error {
3955
req := h.newNetlinkRequest(unix.RTM_NEWADDR, unix.NLM_F_CREATE|unix.NLM_F_REPLACE|unix.NLM_F_ACK)
4056
return h.addrHandle(link, addr, req)
4157
}
4258

4359
// AddrDel will delete an IP address from a link device.
60+
//
4461
// Equivalent to: `ip addr del $addr dev $link`
62+
//
63+
// If `addr` is an IPv4 address and the broadcast address is not given, it
64+
// will be automatically computed based on the IP mask if /30 or larger.
4565
func AddrDel(link Link, addr *Addr) error {
4666
return pkgHandle.AddrDel(link, addr)
4767
}
4868

4969
// AddrDel will delete an IP address from a link device.
5070
// Equivalent to: `ip addr del $addr dev $link`
71+
//
72+
// If `addr` is an IPv4 address and the broadcast address is not given, it
73+
// will be automatically computed based on the IP mask if /30 or larger.
5174
func (h *Handle) AddrDel(link Link, addr *Addr) error {
5275
req := h.newNetlinkRequest(unix.RTM_DELADDR, unix.NLM_F_ACK)
5376
return h.addrHandle(link, addr, req)
@@ -108,14 +131,20 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
108131
}
109132

110133
if family == FAMILY_V4 {
111-
if addr.Broadcast == nil {
134+
// Automatically set the broadcast address if it is unset and the
135+
// subnet is large enough to sensibly have one (/30 or larger).
136+
// See: RFC 3021
137+
if addr.Broadcast == nil && prefixlen < 31 {
112138
calcBroadcast := make(net.IP, masklen/8)
113139
for i := range localAddrData {
114140
calcBroadcast[i] = localAddrData[i] | ^mask[i]
115141
}
116142
addr.Broadcast = calcBroadcast
117143
}
118-
req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
144+
145+
if addr.Broadcast != nil {
146+
req.AddData(nl.NewRtAttr(unix.IFA_BROADCAST, addr.Broadcast))
147+
}
119148

120149
if addr.Label != "" {
121150
labelData := nl.NewRtAttr(unix.IFA_LABEL, nl.ZeroTerminated(addr.Label))

0 commit comments

Comments
 (0)