summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-01-10 08:11:37 +0100
committerThomas Haller <thaller@redhat.com>2020-01-14 16:09:24 +0100
commit71d5550547725edc034da92ebfc3ed507236d683 (patch)
tree9a86d4031ce5de827a1dea60243e600d13dbac80
parente6a9d5b99c7b674c3a932a5e16921eb9e3a7073c (diff)
downloadNetworkManager-71d5550547725edc034da92ebfc3ed507236d683.tar.gz
platform: track IFA_BROADCAST address in NMPlatformIP4Address
- track the broadcast address in NMPlatformIP4Address. For addresses that we receive from kernel and that we cache in NMPlatform, this allows us to show the additional information. For example, we can see it in debug logging. - when setting the address, we still mostly generate our default broadcast address. This is done in the only relevant caller nm_platform_ip4_address_sync(). Basically, we merely moved setting the broadcast address to the caller. That is, because no callers explicitly set the "use_ip4_broadcast_address" flag (yet). However, in the future some caller might want to set an explicit broadcast address. In practice, we currently don't support configuring special broadcast addresses in NetworkManager. Instead, we always add the default one with "address|~netmask" (for plen < 31). Note that a main point of IFA_BROADCAST is to add a broadcast route to the local table. Also note that kernel anyway will add such a "address|~netmask" route, that is regardless whether IFA_BROADCAST is set or not. Hence, setting it or not makes very little difference for normal broadcast addresses -- because kernel tends to add this route either way. It would make a difference if NetworkManager configured an unusual IFA_BROADCAST address or an address for prefixes >= 31 (in which cases kernel wouldn't add them automatically). But we don't do that at the moment. So, while what NM does has little effect in practice, it still seems more correct to add the broadcast address, only so that you see it in `ip addr show`.
-rw-r--r--src/platform/nm-fake-platform.c24
-rw-r--r--src/platform/nm-linux-platform.c24
-rw-r--r--src/platform/nm-platform.c63
-rw-r--r--src/platform/nm-platform.h34
-rw-r--r--src/platform/tests/test-cleanup.c3
-rw-r--r--src/platform/tests/test-common.c1
-rw-r--r--src/platform/tests/test-route.c1
7 files changed, 113 insertions, 37 deletions
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 124432a73c..a3c12becdd 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -938,6 +938,7 @@ ip4_address_add (NMPlatform *platform,
in_addr_t addr,
guint8 plen,
in_addr_t peer_addr,
+ in_addr_t broadcast_address,
guint32 lifetime,
guint32 preferred,
guint32 flags,
@@ -945,16 +946,19 @@ ip4_address_add (NMPlatform *platform,
{
NMPlatformIP4Address address;
- memset (&address, 0, sizeof (address));
- address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
- address.ifindex = ifindex;
- address.address = addr;
- address.peer_address = peer_addr;
- address.plen = plen;
- address.timestamp = nm_utils_get_monotonic_timestamp_sec ();
- address.lifetime = lifetime;
- address.preferred = preferred;
- address.n_ifa_flags = flags;
+ address = (NMPlatformIP4Address) {
+ .addr_source = NM_IP_CONFIG_SOURCE_KERNEL,
+ .ifindex = ifindex,
+ .address = addr,
+ .plen = plen,
+ .peer_address = peer_addr,
+ .broadcast_address = broadcast_address,
+ .use_ip4_broadcast_address = TRUE,
+ .timestamp = nm_utils_get_monotonic_timestamp_sec (),
+ .lifetime = lifetime,
+ .preferred = preferred,
+ .n_ifa_flags = flags,
+ };
if (label)
g_strlcpy (address.label, label, sizeof (address.label));
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 020db21ecd..c6e58284e0 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -3012,6 +3012,12 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
memcpy (&obj->ip4_address.address, nla_data (tb[IFA_LOCAL]), addr_len);
if (tb[IFA_ADDRESS])
memcpy (&obj->ip4_address.peer_address, nla_data (tb[IFA_ADDRESS]), addr_len);
+
+ _check_addr_or_return_null (tb, IFA_BROADCAST, addr_len);
+ obj->ip4_address.broadcast_address = tb[IFA_BROADCAST]
+ ? nla_get_u32 (tb[IFA_BROADCAST])
+ : 0u;
+ obj->ip4_address.use_ip4_broadcast_address = TRUE;
} else {
/* For IPv6, IFA_ADDRESS is always present.
*
@@ -4177,6 +4183,7 @@ _nl_msg_new_address (int nlmsg_type,
int scope,
guint32 lifetime,
guint32 preferred,
+ in_addr_t ip4_broadcast_address,
const char *label)
{
nm_auto_nlmsg struct nl_msg *msg = NULL;
@@ -4220,16 +4227,8 @@ _nl_msg_new_address (int nlmsg_type,
if (label && label[0])
NLA_PUT_STRING (msg, IFA_LABEL, label);
- if ( family == AF_INET
- && nlmsg_type != RTM_DELADDR
- && plen < 31 /* RFC 3021 */
- && address
- && *((in_addr_t *) address) != 0) {
- in_addr_t broadcast;
-
- broadcast = *((in_addr_t *) address) | ~_nm_utils_ip4_prefix_to_netmask (plen);
- NLA_PUT (msg, IFA_BROADCAST, addr_len, &broadcast);
- }
+ if (ip4_broadcast_address != 0)
+ NLA_PUT (msg, IFA_BROADCAST, sizeof (in_addr_t), &ip4_broadcast_address);
if ( lifetime != NM_PLATFORM_LIFETIME_PERMANENT
|| preferred != NM_PLATFORM_LIFETIME_PERMANENT) {
@@ -8005,6 +8004,7 @@ ip4_address_add (NMPlatform *platform,
in_addr_t addr,
guint8 plen,
in_addr_t peer_addr,
+ in_addr_t broadcast_address,
guint32 lifetime,
guint32 preferred,
guint32 flags,
@@ -8024,6 +8024,7 @@ ip4_address_add (NMPlatform *platform,
nm_utils_ip4_address_is_link_local (addr) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE,
lifetime,
preferred,
+ broadcast_address,
label);
nmp_object_stackinit_id_ip4_address (&obj_id, ifindex, addr, plen, peer_addr);
@@ -8054,6 +8055,7 @@ ip6_address_add (NMPlatform *platform,
RT_SCOPE_UNIVERSE,
lifetime,
preferred,
+ 0,
NULL);
nmp_object_stackinit_id_ip6_address (&obj_id, ifindex, &addr);
@@ -8077,6 +8079,7 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 pl
RT_SCOPE_NOWHERE,
NM_PLATFORM_LIFETIME_PERMANENT,
NM_PLATFORM_LIFETIME_PERMANENT,
+ 0,
NULL);
if (!nlmsg)
g_return_val_if_reached (FALSE);
@@ -8102,6 +8105,7 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, gui
RT_SCOPE_NOWHERE,
NM_PLATFORM_LIFETIME_PERMANENT,
NM_PLATFORM_LIFETIME_PERMANENT,
+ 0,
NULL);
if (!nlmsg)
g_return_val_if_reached (FALSE);
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 2065b1818e..82d79d7a44 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -3314,6 +3314,7 @@ nm_platform_ip4_address_add (NMPlatform *self,
in_addr_t address,
guint8 plen,
in_addr_t peer_address,
+ in_addr_t broadcast_address,
guint32 lifetime,
guint32 preferred,
guint32 flags,
@@ -3328,22 +3329,26 @@ nm_platform_ip4_address_add (NMPlatform *self,
g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE);
if (_LOGD_ENABLED ()) {
- NMPlatformIP4Address addr = { 0 };
-
- addr.ifindex = ifindex;
- addr.address = address;
- addr.peer_address = peer_address;
- addr.plen = plen;
- addr.timestamp = 0; /* set it at zero, which to_string will treat as *now* */
- addr.lifetime = lifetime;
- addr.preferred = preferred;
- addr.n_ifa_flags = flags;
+ NMPlatformIP4Address addr;
+
+ addr = (NMPlatformIP4Address) {
+ .ifindex = ifindex,
+ .address = address,
+ .peer_address = peer_address,
+ .plen = plen,
+ .timestamp = 0, /* set it at zero, which to_string will treat as *now* */
+ .lifetime = lifetime,
+ .preferred = preferred,
+ .n_ifa_flags = flags,
+ .broadcast_address = broadcast_address,
+ .use_ip4_broadcast_address = TRUE,
+ };
if (label)
g_strlcpy (addr.label, label, sizeof (addr.label));
_LOG3D ("address: adding or updating IPv4 address: %s", nm_platform_ip4_address_to_string (&addr, NULL, 0));
}
- return klass->ip4_address_add (self, ifindex, address, plen, peer_address, lifetime, preferred, flags, label);
+ return klass->ip4_address_add (self, ifindex, address, plen, peer_address, broadcast_address, lifetime, preferred, flags, label);
}
gboolean
@@ -3802,8 +3807,14 @@ nm_platform_ip4_address_sync (NMPlatform *self,
if (!lifetime)
goto delete_and_next2;
- if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->plen,
- known_address->peer_address, lifetime, preferred,
+ if (!nm_platform_ip4_address_add (self,
+ ifindex,
+ known_address->address,
+ known_address->plen,
+ known_address->peer_address,
+ nm_platform_ip4_broadcast_address_from_addr (known_address),
+ lifetime,
+ preferred,
ifa_flags,
known_address->label))
goto delete_and_next2;
@@ -5708,6 +5719,8 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu
char *str_peer = NULL;
const char *str_lft_p, *str_pref_p, *str_time_p;
gint32 now = nm_utils_get_monotonic_timestamp_sec ();
+ in_addr_t broadcast_address;
+ char str_broadcast[INET_ADDRSTRLEN];
if (!nm_utils_to_string_buffer_init_null (address, &buf, &len))
return buf;
@@ -5736,9 +5749,27 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu
now, str_pref, sizeof (str_pref)) );
str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time));
+ broadcast_address = nm_platform_ip4_broadcast_address_from_addr (address);
+
g_snprintf (buf, len,
- "%s/%d lft %s pref %s%s%s%s%s%s src %s%s",
- s_address, address->plen, str_lft_p, str_pref_p, str_time_p,
+ "%s/%d"
+ "%s%s" /* broadcast */
+ " lft %s"
+ " pref %s"
+ "%s" /* time */
+ "%s" /* peer */
+ "%s" /* dev */
+ "%s" /* flags */
+ "%s" /* label */
+ " src %s"
+ "%s" /* external */
+ "",
+ s_address, address->plen,
+ broadcast_address ? " brd " : "",
+ broadcast_address ? nm_utils_inet4_ntop (broadcast_address, str_broadcast) : "",
+ str_lft_p,
+ str_pref_p,
+ str_time_p,
str_peer ?: "",
str_dev,
_to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)),
@@ -6966,6 +6997,7 @@ nm_platform_ip4_address_hash_update (const NMPlatformIP4Address *obj, NMHashStat
nm_hash_update_vals (h,
obj->ifindex,
obj->addr_source,
+ nm_platform_ip4_broadcast_address_from_addr (obj),
obj->timestamp,
obj->lifetime,
obj->preferred,
@@ -6985,6 +7017,7 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A
NM_CMP_FIELD (a, b, address);
NM_CMP_FIELD (a, b, plen);
NM_CMP_FIELD (a, b, peer_address);
+ NM_CMP_DIRECT (nm_platform_ip4_broadcast_address_from_addr (a), nm_platform_ip4_broadcast_address_from_addr (b));
NM_CMP_FIELD (a, b, addr_source);
NM_CMP_FIELD (a, b, timestamp);
NM_CMP_FIELD (a, b, lifetime);
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index d18208081a..ace465fed1 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -308,6 +308,8 @@ typedef enum {
guint8 plen; \
\
bool external:1; \
+ \
+ bool use_ip4_broadcast_address:1; \
;
/**
@@ -344,6 +346,12 @@ struct _NMPlatformIP4Address {
* */
in_addr_t peer_address; /* PTP peer address */
+ /* IFA_BROADCAST.
+ *
+ * This parameter is ignored unless use_ip4_broadcast_address is TRUE.
+ * See nm_platform_ip4_broadcast_address_from_addr(). */
+ in_addr_t broadcast_address;
+
char label[NMP_IFNAMSIZ];
};
@@ -1080,6 +1088,7 @@ typedef struct {
in_addr_t address,
guint8 plen,
in_addr_t peer_address,
+ in_addr_t broadcast_address,
guint32 lifetime,
guint32 preferred_lft,
guint32 flags,
@@ -1151,6 +1160,30 @@ NMPlatform *nm_platform_get (void);
/*****************************************************************************/
+static inline in_addr_t
+nm_platform_ip4_broadcast_address_create (in_addr_t address,
+ guint8 plen)
+{
+ return address | ~_nm_utils_ip4_prefix_to_netmask (plen);
+}
+
+static inline in_addr_t
+nm_platform_ip4_broadcast_address_from_addr (const NMPlatformIP4Address *addr)
+{
+ nm_assert (addr);
+
+ if (addr->use_ip4_broadcast_address)
+ return addr->broadcast_address;
+
+ /* the set broadcast-address gets ignored, and we determine a default brd. */
+ if ( addr->address != 0u
+ && addr->plen < 31 /* RFC3021 */)
+ return nm_platform_ip4_broadcast_address_create (addr->address, addr->plen);
+ return 0u;
+}
+
+/*****************************************************************************/
+
/**
* nm_platform_route_table_coerce:
* @table: the route table, in its original value as received
@@ -1727,6 +1760,7 @@ gboolean nm_platform_ip4_address_add (NMPlatform *self,
in_addr_t address,
guint8 plen,
in_addr_t peer_address,
+ in_addr_t broadcast_address,
guint32 lifetime,
guint32 preferred_lft,
guint32 flags,
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index 34175c0160..d19ff1f0af 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -61,8 +61,7 @@ test_cleanup_internal (void)
break;
});
- /* Add routes and addresses */
- g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, lifetime, preferred, 0, NULL));
+ g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, nm_platform_ip4_broadcast_address_create (addr4, plen4), lifetime, preferred, 0, NULL));
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr6, plen6, in6addr_any, lifetime, preferred, flags));
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss);
nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss);
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
index 2fbfb90d4c..f6a77daa08 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -867,6 +867,7 @@ _ip_address_add (NMPlatform *platform,
address->addr4,
plen,
peer_address->addr4,
+ 0u,
lifetime,
preferred,
flags,
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index e2c1ed80e4..707313b4ca 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -544,6 +544,7 @@ test_ip4_route_options (gconstpointer test_data)
a->address,
a->plen,
a->peer_address,
+ nm_platform_ip4_broadcast_address_create (a->address, a->plen),
a->lifetime,
a->preferred,
a->n_ifa_flags,