}
}
-static bool address_may_have_broadcast(const Address *a) {
+static bool address_needs_to_set_broadcast(const Address *a, Link *link) {
assert(a);
+ assert(link);
if (a->family != AF_INET)
return false;
if (a->prefixlen > 30)
return false;
- if (a->set_broadcast >= 0)
- return a->set_broadcast;
-
- return true; /* Defaults to true. */
-}
-
-void address_set_broadcast(Address *a) {
- assert(a);
-
- if (!address_may_have_broadcast(a))
- return;
-
/* If explicitly configured, do not update the address. */
if (in4_addr_is_set(&a->broadcast))
- return;
+ return false;
- /* If Address= is 0.0.0.0, then the broadcast address will be set later in address_acquire(). */
- if (in4_addr_is_null(&a->in_addr.in))
- return;
+ if (a->set_broadcast >= 0)
+ return a->set_broadcast;
- a->broadcast.s_addr = a->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> a->prefixlen);
+ /* Defaults to true, except for wireguard, as typical configuration for wireguard does not set
+ * broadcast. */
+ return !streq_ptr(link->kind, "wireguard");
}
-static bool address_may_set_broadcast(const Address *a, const Link *link) {
+void address_set_broadcast(Address *a, Link *link) {
assert(a);
assert(link);
- if (!address_may_have_broadcast(a))
- return false;
+ if (!address_needs_to_set_broadcast(a, link))
+ return;
- /* Typical configuration for wireguard does not set broadcast. */
- return !streq_ptr(link->kind, "wireguard");
+ a->broadcast.s_addr = a->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> a->prefixlen);
}
static struct ifa_cacheinfo *address_set_cinfo(const Address *a, struct ifa_cacheinfo *cinfo) {
return r;
na->in_addr = in_addr;
- address_set_broadcast(na);
*ret = TAKE_PTR(na);
return 1;
r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m");
- } else if (address_may_set_broadcast(address, link)) {
+ } else if (in4_addr_is_set(&address->broadcast)) {
r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m");
consume_object = true;
}
+ if (address_needs_to_set_broadcast(address, link)) {
+ if (!consume_object) {
+ Address *a;
+
+ r = address_dup(address, &a);
+ if (r < 0)
+ return r;
+
+ address = a;
+ consume_object = true;
+ }
+
+ address_set_broadcast(address, link);
+ }
+
if (address_get(link, address, &existing) < 0) {
_cleanup_(address_freep) Address *tmp = NULL;
address->section->filename, address->section->line);
}
- if (address_may_have_broadcast(address))
- address_set_broadcast(address);
- else if (address->broadcast.s_addr != 0) {
- log_warning("%s: broadcast address is set for IPv6 address or IPv4 address with prefixlength larger than 30. "
+ if (in4_addr_is_set(&address->broadcast) &&
+ (address->family == AF_INET6 || address->prefixlen > 30 ||
+ in_addr_is_set(address->family, &address->in_addr_peer))) {
+ log_warning("%s: broadcast address is set for an IPv6 address, "
+ "an IPv4 address with peer address, or with prefix length larger than 30. "
"Ignoring Broadcast= setting in the [Address] section from line %u.",
address->section->filename, address->section->line);