summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-10-21 23:17:11 +0200
committerThomas Haller <thaller@redhat.com>2015-11-02 13:57:01 +0100
commit6c8aa669a4a6be86e29b45fc1a39aadcca9478b0 (patch)
tree3e19cad9c238c428ecc4469818da34f8f4926781
parentaa5b89a2ec8db5735925f78f3c91885a513ce51e (diff)
downloadNetworkManager-6c8aa669a4a6be86e29b45fc1a39aadcca9478b0.tar.gz
platform: properly handle IPv4 peer-addresses
The peer-address (IFA_ADDRESS) can also be all-zero (0.0.0.0). That is distinct from an usual address without explicit peer-address, which implicitly has the same peer and local address. Previously, we treated an all-zero peer_address as having peer and local address equal. This is especially grave, because the peer is part of the primary key for an IPv4 address. So we not only get a property of the address wrong, but we wrongly consider two different addresses as one and the same. To properly handle these addresses, we always must explicitly set the peer.
-rw-r--r--src/devices/nm-device.c11
-rw-r--r--src/devices/wwan/nm-modem-broadband.c1
-rw-r--r--src/dhcp-manager/nm-dhcp-dhclient-utils.c1
-rw-r--r--src/dhcp-manager/nm-dhcp-systemd.c1
-rw-r--r--src/dhcp-manager/nm-dhcp-utils.c10
-rw-r--r--src/dhcp-manager/tests/test-dhcp-dhclient.c2
-rw-r--r--src/dhcp-manager/tests/test-dhcp-utils.c2
-rw-r--r--src/dnsmasq-manager/tests/test-dnsmasq-utils.c3
-rw-r--r--src/nm-ip4-config.c14
-rw-r--r--src/platform/nm-fake-platform.c61
-rw-r--r--src/platform/nm-linux-platform.c56
-rw-r--r--src/platform/nm-platform.c54
-rw-r--r--src/platform/nm-platform.h17
-rw-r--r--src/platform/nmp-object.c8
-rw-r--r--src/platform/tests/platform.c15
-rw-r--r--src/platform/tests/test-address.c81
-rw-r--r--src/platform/tests/test-cleanup.c2
-rw-r--r--src/platform/tests/test-common.c27
-rw-r--r--src/ppp-manager/nm-ppp-manager.c9
-rw-r--r--src/tests/test-ip4-config.c4
-rw-r--r--src/vpn-manager/nm-vpn-connection.c2
21 files changed, 227 insertions, 154 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 9fe3d2ac71..f740f0ad5a 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -3274,8 +3274,7 @@ ipv4ll_get_ip4_config (NMDevice *self, guint32 lla)
g_assert (config);
memset (&address, 0, sizeof (address));
- address.address = lla;
- address.plen = 16;
+ nm_platform_ip4_address_set_addr (&address, lla, 16);
address.source = NM_IP_CONFIG_SOURCE_IP4LL;
nm_ip4_config_add_address (config, &address);
@@ -4016,10 +4015,11 @@ reserve_shared_ip (NMDevice *self, NMSettingIPConfig *s_ip4, NMPlatformIP4Addres
if (s_ip4 && nm_setting_ip_config_get_num_addresses (s_ip4)) {
/* Use the first user-supplied address */
NMIPAddress *user = nm_setting_ip_config_get_address (s_ip4, 0);
+ in_addr_t a;
g_assert (user);
- nm_ip_address_get_address_binary (user, &address->address);
- address->plen = nm_ip_address_get_prefix (user);
+ nm_ip_address_get_address_binary (user, &a);
+ nm_platform_ip4_address_set_addr (address, a, nm_ip_address_get_prefix (user));
} else {
/* Find an unused address in the 10.42.x.x range */
guint32 start = (guint32) ntohl (0x0a2a0001); /* 10.42.0.1 */
@@ -4032,8 +4032,7 @@ reserve_shared_ip (NMDevice *self, NMSettingIPConfig *s_ip4, NMPlatformIP4Addres
return FALSE;
}
}
- address->address = start + count;
- address->plen = 24;
+ nm_platform_ip4_address_set_addr (address, start + count, 24);
g_hash_table_insert (shared_ips,
GUINT_TO_POINTER (address->address),
diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c
index 7ec90c33ef..2236559477 100644
--- a/src/devices/wwan/nm-modem-broadband.c
+++ b/src/devices/wwan/nm-modem-broadband.c
@@ -750,6 +750,7 @@ static_stage3_ip4_done (NMModemBroadband *self)
memset (&address, 0, sizeof (address));
address.address = address_network;
+ address.peer_address = address_network;
address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config);
address.source = NM_IP_CONFIG_SOURCE_WWAN;
nm_ip4_config_add_address (config, &address);
diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c
index a86596c077..726d26c8d0 100644
--- a/src/dhcp-manager/nm-dhcp-dhclient-utils.c
+++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c
@@ -675,6 +675,7 @@ nm_dhcp_dhclient_read_lease_ip_configs (const char *iface,
continue;
if (!inet_pton (AF_INET, value, &address.address))
continue;
+ address.peer_address = address.address;
/* Gateway */
value = g_hash_table_lookup (hash, "option routers");
diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c
index 4459fd583f..e508ea13bb 100644
--- a/src/dhcp-manager/nm-dhcp-systemd.c
+++ b/src/dhcp-manager/nm-dhcp-systemd.c
@@ -232,6 +232,7 @@ lease_to_ip4_config (const char *iface,
sd_dhcp_lease_get_address (lease, &tmp_addr);
memset (&address, 0, sizeof (address));
address.address = tmp_addr.s_addr;
+ address.peer_address = tmp_addr.s_addr;
str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL);
LOG_LEASE (LOGD_DHCP4, " address %s", str);
add_option (options, dhcp4_requests, DHCP_OPTION_IP_ADDRESS, str);
diff --git a/src/dhcp-manager/nm-dhcp-utils.c b/src/dhcp-manager/nm-dhcp-utils.c
index c7c246a7ce..e6bc18072c 100644
--- a/src/dhcp-manager/nm-dhcp-utils.c
+++ b/src/dhcp-manager/nm-dhcp-utils.c
@@ -380,6 +380,7 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex,
{
NMIP4Config *ip4_config = NULL;
guint32 tmp_addr;
+ in_addr_t addr;
NMPlatformIP4Address address;
char *str = NULL;
guint32 gwaddr = 0, plen = 0;
@@ -391,10 +392,9 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex,
address.timestamp = nm_utils_get_monotonic_timestamp_s ();
str = g_hash_table_lookup (options, "ip_address");
- if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) {
- address.address = tmp_addr;
+ if (str && (inet_pton (AF_INET, str, &addr) > 0))
nm_log_info (LOGD_DHCP4, " address %s", str);
- } else
+ else
goto error;
str = g_hash_table_lookup (options, "subnet_mask");
@@ -403,10 +403,10 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex,
nm_log_info (LOGD_DHCP4, " plen %d (%s)", plen, str);
} else {
/* Get default netmask for the IP according to appropriate class. */
- plen = nm_utils_ip4_get_default_prefix (address.address);
+ plen = nm_utils_ip4_get_default_prefix (addr);
nm_log_info (LOGD_DHCP4, " plen %d (default)", plen);
}
- address.plen = plen;
+ nm_platform_ip4_address_set_addr (&address, addr, plen);
/* Routes: if the server returns classless static routes, we MUST ignore
* the 'static_routes' option.
diff --git a/src/dhcp-manager/tests/test-dhcp-dhclient.c b/src/dhcp-manager/tests/test-dhcp-dhclient.c
index 15817addb4..ce3697a552 100644
--- a/src/dhcp-manager/tests/test-dhcp-dhclient.c
+++ b/src/dhcp-manager/tests/test-dhcp-dhclient.c
@@ -666,6 +666,7 @@ test_read_lease_ip4_config_basic (void)
g_assert (inet_aton ("192.168.1.180", (struct in_addr *) &expected_addr));
addr = nm_ip4_config_get_address (config, 0);
g_assert_cmpint (addr->address, ==, expected_addr);
+ g_assert_cmpint (addr->peer_address, ==, expected_addr);
g_assert_cmpint (addr->plen, ==, 24);
/* Gateway */
@@ -688,6 +689,7 @@ test_read_lease_ip4_config_basic (void)
g_assert (inet_aton ("10.77.52.141", (struct in_addr *) &expected_addr));
addr = nm_ip4_config_get_address (config, 0);
g_assert_cmpint (addr->address, ==, expected_addr);
+ g_assert_cmpint (addr->peer_address, ==, expected_addr);
g_assert_cmpint (addr->plen, ==, 8);
/* Gateway */
diff --git a/src/dhcp-manager/tests/test-dhcp-utils.c b/src/dhcp-manager/tests/test-dhcp-utils.c
index 65a396092a..49987c40ca 100644
--- a/src/dhcp-manager/tests/test-dhcp-utils.c
+++ b/src/dhcp-manager/tests/test-dhcp-utils.c
@@ -95,7 +95,7 @@ test_generic_options (void)
address = nm_ip4_config_get_address (ip4_config, 0);
g_assert (inet_pton (AF_INET, expected_addr, &tmp) > 0);
g_assert (address->address == tmp);
- g_assert (address->peer_address == 0);
+ g_assert (address->peer_address == tmp);
g_assert_cmpint (address->plen, ==, 24);
/* Gateway */
diff --git a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c
index 98d308337f..04bf1b4d74 100644
--- a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c
+++ b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c
@@ -31,8 +31,7 @@ static NMPlatformIP4Address *
_set_addr (NMPlatformIP4Address *addr, const char *address, int plen)
{
memset (addr, 0, sizeof (*addr));
- addr->address = nmtst_inet4_from_string (address);
- addr->plen = plen;
+ nm_platform_ip4_address_set_addr (addr, nmtst_inet4_from_string (address), plen);
return addr;
}
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 5c35605d4b..7e74379ec0 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -180,7 +180,7 @@ addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Addre
{
return a->address == b->address
&& a->plen == b->plen
- && nm_platform_ip4_address_equal_peer_net (a, b);
+ && ((a->peer_address ^ b->peer_address) & nm_utils_ip4_prefix_to_netmask (a->plen)) == 0;
}
static gboolean
@@ -309,7 +309,7 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu
route.source = NM_IP_CONFIG_SOURCE_KERNEL;
/* The destination network depends on the peer-address. */
- route.network = nm_utils_ip4_address_clear_host_address (nm_platform_ip4_address_get_peer (addr), addr->plen);
+ route.network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen);
if (_ipv4_is_zeronet (route.network)) {
/* Kernel doesn't add device-routes for destinations that
@@ -404,6 +404,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu
memset (&address, 0, sizeof (address));
nm_ip_address_get_address_binary (s_addr, &address.address);
+ address.peer_address = address.address;
address.plen = nm_ip_address_get_prefix (s_addr);
address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
@@ -1005,7 +1006,7 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
dst_addr = nm_ip4_config_get_address (dst, i))) {
are_equal = FALSE;
if ( !addresses_are_duplicate (src_addr, dst_addr)
- || (nm_platform_ip4_address_get_peer (src_addr) != nm_platform_ip4_address_get_peer (dst_addr))) {
+ || src_addr->peer_address != dst_addr->peer_address) {
has_relevant_changes = TRUE;
break;
}
@@ -1273,7 +1274,7 @@ nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network,
if (item->plen > plen)
continue;
- peer_network = nm_utils_ip4_address_clear_host_address (nm_platform_ip4_address_get_peer (item), item->plen);
+ peer_network = nm_utils_ip4_address_clear_host_address (item->peer_address, item->plen);
if (_ipv4_is_zeronet (peer_network))
continue;
@@ -2013,7 +2014,7 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only
const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
hash_u32 (sum, address->address);
hash_u32 (sum, address->plen);
- hash_u32 (sum, nm_platform_ip4_address_get_peer_net (address));
+ hash_u32 (sum, address->peer_address & nm_utils_ip4_prefix_to_netmask (address->plen));
}
for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) {
@@ -2160,8 +2161,7 @@ get_property (GObject *object, guint prop_id,
g_variant_builder_add (&addr_builder, "{sv}",
"prefix",
g_variant_new_uint32 (address->plen));
- if ( address->peer_address
- && address->peer_address != address->address) {
+ if (address->peer_address != address->address) {
g_variant_builder_add (&addr_builder, "{sv}",
"peer",
g_variant_new_string (nm_utils_inet4_ntop (address->peer_address, NULL)));
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index d5dae69915..9d4f0553c4 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -100,6 +100,14 @@ static gboolean ip6_address_delete (NMPlatform *platform, int ifindex, struct in
/******************************************************************/
static gboolean
+_ip4_address_equal_peer_net (in_addr_t peer1, in_addr_t peer2, int plen)
+{
+ return ((peer1 ^ peer2) & nm_utils_ip4_prefix_to_netmask (plen)) == 0;
+}
+
+/******************************************************************/
+
+static gboolean
sysctl_set (NMPlatform *platform, const char *path, const char *value)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
@@ -871,7 +879,7 @@ ip4_address_add (NMPlatform *platform,
address.source = NM_IP_CONFIG_SOURCE_KERNEL;
address.ifindex = ifindex;
address.address = addr;
- address.peer_address = peer_addr && peer_addr != addr ? peer_addr : 0;
+ address.peer_address = peer_addr;
address.plen = plen;
address.timestamp = nm_utils_get_monotonic_timestamp_s ();
address.lifetime = lifetime;
@@ -881,18 +889,19 @@ ip4_address_add (NMPlatform *platform,
for (i = 0; i < priv->ip4_addresses->len; i++) {
NMPlatformIP4Address *item = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
+ gboolean changed;
- if (item->ifindex != address.ifindex)
- continue;
- if (item->address != address.address)
- continue;
- if (item->plen != address.plen)
- continue;
- if (!nm_platform_ip4_address_equal_peer_net (item, &address))
+ if ( item->ifindex != address.ifindex
+ || item->address != address.address
+ || item->plen != address.plen
+ || !_ip4_address_equal_peer_net (item->peer_address, address.peer_address, address.plen))
continue;
+ changed = !nm_platform_ip4_address_cmp (item, &address);
+
memcpy (item, &address, sizeof (address));
- g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
+ if (changed)
+ g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
return TRUE;
}
@@ -928,18 +937,17 @@ ip6_address_add (NMPlatform *platform,
for (i = 0; i < priv->ip6_addresses->len; i++) {
NMPlatformIP6Address *item = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
+ gboolean changed;
- if (item->ifindex != address.ifindex)
- continue;
- if (!IN6_ARE_ADDR_EQUAL (&item->address, &address.address))
- continue;
- if (item->plen != address.plen)
+ if ( item->ifindex != address.ifindex
+ || !IN6_ARE_ADDR_EQUAL (&item->address, &address.address))
continue;
- if (nm_platform_ip6_address_cmp (item, &address) != 0) {
- memcpy (item, &address, sizeof (address));
+ changed = !nm_platform_ip6_address_cmp (item, &address);
+
+ memcpy (item, &address, sizeof (address));
+ if (changed)
g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex, &address, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_INTERNAL);
- }
return TRUE;
}
@@ -958,8 +966,10 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen,
for (i = 0; i < priv->ip4_addresses->len; i++) {
NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
- if (address->ifindex == ifindex && address->plen == plen && address->address == addr &&
- (!peer_address || address->peer_address == peer_address)) {
+ if ( address->ifindex == ifindex
+ && address->plen == plen
+ && address->address == addr
+ && ((peer_address ^ address->peer_address) & nm_utils_ip4_prefix_to_netmask (plen)) == 0) {
NMPlatformIP4Address deleted_address;
memcpy (&deleted_address, address, sizeof (deleted_address));
@@ -981,8 +991,9 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int
for (i = 0; i < priv->ip6_addresses->len; i++) {
NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
- if (address->ifindex == ifindex && address->plen == plen
- && IN6_ARE_ADDR_EQUAL (&address->address, &addr)) {
+ if ( address->ifindex == ifindex
+ && address->plen == plen
+ && IN6_ARE_ADDR_EQUAL (&address->address, &addr)) {
NMPlatformIP6Address deleted_address;
memcpy (&deleted_address, address, sizeof (deleted_address));
@@ -1000,12 +1011,6 @@ ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
- NMPlatformIP4Address a = {
- .ifindex = ifindex,
- .address = addr,
- .plen = plen,
- .peer_address = peer_address,
- };
for (i = 0; i < priv->ip4_addresses->len; i++) {
NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
@@ -1013,7 +1018,7 @@ ip4_address_get (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in
if ( address->ifindex == ifindex
&& address->plen == plen
&& address->address == addr
- && nm_platform_ip4_address_equal_peer_net (address, &a))
+ && _ip4_address_equal_peer_net (address->peer_address, peer_address, plen))
return address;
}
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 2e148abc9c..3bcc43d56c 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -1442,23 +1442,32 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
obj->ip_address.ifindex = ifa->ifa_index;
obj->ip_address.plen = ifa->ifa_prefixlen;
- if (_check_addr_or_errout (tb, IFA_LOCAL, addr_len))
- memcpy (obj->ip_address.address_ptr, nla_data (tb[IFA_LOCAL]), addr_len);
-
- if (_check_addr_or_errout (tb, IFA_ADDRESS, addr_len)) {
- NMIPAddr *a = nla_data (tb[IFA_ADDRESS]);
-
- /* 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 */
- if ( !tb[IFA_LOCAL]
- || !memcmp (a, obj->ip_address.address_ptr, addr_len)) {
- memcpy (obj->ip_address.address_ptr, a, addr_len);
- } else {
- if (is_v4)
- obj->ip4_address.peer_address = a->addr4;
- else
- obj->ip6_address.peer_address = a->addr6;
+ _check_addr_or_errout (tb, IFA_ADDRESS, addr_len);
+ _check_addr_or_errout (tb, IFA_LOCAL, addr_len);
+ if (is_v4) {
+ /* For IPv4, kernel omits IFA_LOCAL/IFA_ADDRESS if (and only if) they
+ * are effectively 0.0.0.0 (all-zero). */
+ if (tb[IFA_LOCAL])
+ 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);
+ } else {
+ /* For IPv6, IFA_ADDRESS is always present.
+ *
+ * If IFA_LOCAL is missing, IFA_ADDRESS is @address and @peer_address
+ * is :: (all-zero).
+ *
+ * If unexpectely IFA_ADDRESS is missing, make the best of it -- but it _should_
+ * actually be there. */
+ if (tb[IFA_ADDRESS] || tb[IFA_LOCAL]) {
+ if (tb[IFA_LOCAL]) {
+ memcpy (&obj->ip6_address.address, nla_data (tb[IFA_LOCAL]), addr_len);
+ if (tb[IFA_ADDRESS])
+ memcpy (&obj->ip6_address.peer_address, nla_data (tb[IFA_ADDRESS]), addr_len);
+ else
+ obj->ip6_address.peer_address = obj->ip6_address.address;
+ } else
+ memcpy (&obj->ip6_address.address, nla_data (tb[IFA_ADDRESS]), addr_len);
}
}
@@ -4256,7 +4265,14 @@ build_rtnl_addr (NMPlatform *platform,
}
/* Peer/point-to-point address */
- if (peer_addr) {
+ if ( peer_addr
+ && family == AF_INET
+ && (*((in_addr_t *) peer_addr)) == (*((in_addr_t *) addr))) {
+ /* For IPv4, a local address being equal the peer address means that
+ * no explict peer is set.
+ *
+ * We don't have to set it explicitly. */
+ } else if (peer_addr) {
auto_nl_addr struct nl_addr *nlpeer = _nl_addr_build (family, peer_addr, addrlen);
nle = rtnl_addr_set_peer (rtnladdr, nlpeer);
@@ -4308,7 +4324,7 @@ _nmp_vt_cmd_plobj_to_nl_ip4_address (NMPlatform *platform, const NMPlatformObjec
AF_INET,
obj->ifindex,
&obj->address,
- obj->peer_address ? &obj->peer_address : NULL,
+ &obj->peer_address,
obj->plen,
lifetime,
preferred,
@@ -4351,7 +4367,7 @@ ip4_address_add (NMPlatform *platform,
auto_nl_object struct nl_object *nlo = NULL;
nlo = build_rtnl_addr (platform, AF_INET, ifindex, &addr,
- peer_addr ? &peer_addr : NULL,
+ &peer_addr,
plen, lifetime, preferred, 0,
label);
return do_add_addrroute (platform,
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 6158f890ec..4827638137 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -1956,10 +1956,12 @@ _to_string_dev (NMPlatform *self, int ifindex, char *buf, size_t size)
/******************************************************************/
-in_addr_t
-nm_platform_ip4_address_get_peer (const NMPlatformIP4Address *addr)
+void
+nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, int plen)
{
- return addr->peer_address ?: addr->address;
+ addr->address = address;
+ addr->peer_address = address;
+ addr->plen = plen;
}
const struct in6_addr *
@@ -1971,28 +1973,6 @@ nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr)
return &addr->peer_address;
}
-in_addr_t
-nm_platform_ip4_address_get_peer_net (const NMPlatformIP4Address *addr)
-{
- return (addr->peer_address ?: addr->address) & nm_utils_ip4_prefix_to_netmask (addr->plen);
-}
-
-gboolean
-nm_platform_ip4_address_equal_peer_net (const NMPlatformIP4Address *addr1, const NMPlatformIP4Address *addr2)
-{
- guint32 a1, a2;
-
- if (addr1->plen != addr2->plen)
- return FALSE;
-
- /* For kernel, if the peer address is unset, that effectively means that
- * the peer address equals the local address. */
- a1 = addr1->peer_address ? addr1->peer_address : addr1->address;
- a2 = addr2->peer_address ? addr2->peer_address : addr2->address;
-
- return ((a1 ^ a2) & nm_utils_ip4_prefix_to_netmask (addr1->plen)) == 0;
-}
-
GArray *
nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex)
{
@@ -2091,7 +2071,8 @@ gboolean
nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address)
{
char str_dev[TO_STRING_DEV_BUF_SIZE];
- char str_peer[NM_UTILS_INET_ADDRSTRLEN];
+ char str_peer2[NM_UTILS_INET_ADDRSTRLEN];
+ char str_peer[100];
_CHECK_SELF (self, klass, FALSE);
@@ -2099,11 +2080,10 @@ nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address
g_return_val_if_fail (plen > 0, FALSE);
g_return_val_if_fail (klass->ip4_address_delete, FALSE);
- _LOGD ("address: deleting IPv4 address %s/%d, %s%s%sifindex %d%s",
+ _LOGD ("address: deleting IPv4 address %s/%d, %sifindex %d%s",
nm_utils_inet4_ntop (address, NULL), plen,
- peer_address ? "peer " : "",
- peer_address ? nm_utils_inet4_ntop (peer_address, str_peer) : "",
- peer_address ? ", " : "",
+ peer_address != address
+ ? nm_sprintf_buf (str_peer, "peer %s, ", nm_utils_inet4_ntop (peer_address, str_peer2)) : "",
ifindex,
_to_string_dev (self, ifindex, str_dev, sizeof (str_dev)));
return klass->ip4_address_delete (self, ifindex, address, plen, peer_address);
@@ -2157,7 +2137,7 @@ array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address
if ( candidate->address == address->address
&& candidate->plen == address->plen
- && nm_platform_ip4_address_equal_peer_net (candidate, address)) {
+ && ((candidate->peer_address & address->peer_address) & nm_utils_ip4_prefix_to_netmask (address->plen)) == 0) {
guint32 lifetime, preferred;
if (nmp_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred,
@@ -2831,7 +2811,7 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu
inet_ntop (AF_INET, &address->address, s_address, sizeof (s_address));
- if (address->peer_address) {
+ if (address->peer_address != address->address) {
inet_ntop (AF_INET, &address->peer_address, s_peer, sizeof (s_peer));
str_peer = g_strconcat (" ptp ", s_peer, NULL);
}
@@ -3237,20 +3217,12 @@ nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan
int
nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
{
- in_addr_t p_a, p_b;
-
_CMP_SELF (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, source);
_CMP_FIELD (a, b, address);
_CMP_FIELD (a, b, plen);
-
- /* a peer-address of zero is the same as setting it to address.
- * Here we consider the full address, including the host-part. */
- p_a = nm_platform_ip4_address_get_peer (a);
- p_b = nm_platform_ip4_address_get_peer (b);
- _CMP_DIRECT (p_a, p_b);
-
+ _CMP_FIELD (a, b, peer_address);
_CMP_FIELD (a, b, timestamp);
_CMP_FIELD (a, b, lifetime);
_CMP_FIELD (a, b, preferred);
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 39d766e0d2..2522f3092f 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -234,8 +234,21 @@ typedef struct {
**/
struct _NMPlatformIP4Address {
__NMPlatformIPAddress_COMMON;
+
+ /* The local address IFA_LOCAL. */
in_addr_t address;
+
+ /* The IFA_ADDRESS PTP peer address. This field is rather important, because
+ * it constitutes the identifier for the IPv4 address (e.g. you can add two
+ * addresses that only differ by their peer's network-part.
+ *
+ * Beware that for most cases, NetworkManager doesn't want to set an explicit
+ * peer-address. Hoever, that corresponds to setting the peer address to @address
+ * itself. Leaving peer-address unset/zero, means explicitly setting the peer
+ * address to 0.0.0.0, which you probably don't want.
+ * */
in_addr_t peer_address; /* PTP peer address */
+
char label[IFNAMSIZ];
};
@@ -715,10 +728,8 @@ guint32 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex);
gboolean nm_platform_mesh_set_channel (NMPlatform *self, int ifindex, guint32 channel);
gboolean nm_platform_mesh_set_ssid (NMPlatform *self, int ifindex, const guint8 *ssid, gsize len);
-in_addr_t nm_platform_ip4_address_get_peer (const NMPlatformIP4Address *addr);
+void nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, int plen);
const struct in6_addr *nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr);
-in_addr_t nm_platform_ip4_address_get_peer_net (const NMPlatformIP4Address *addr);
-gboolean nm_platform_ip4_address_equal_peer_net (const NMPlatformIP4Address *addr1, const NMPlatformIP4Address *addr2);
const NMPlatformIP4Address *nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 0f9a4fbf69..a783021d83 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -466,8 +466,8 @@ _vt_cmd_plobj_to_string_id_##type (const NMPlatformObject *_obj, char *buf, gsiz
}
_vt_cmd_plobj_to_string_id (link, NMPlatformLink, "%d", obj->ifindex);
_vt_cmd_plobj_to_string_id (ip4_address, NMPlatformIP4Address, "%d: %s/%d%s%s", obj->ifindex, nm_utils_inet4_ntop ( obj->address, buf1), obj->plen,
- obj->peer_address && obj->peer_address != obj->address ? "," : "",
- obj->peer_address && obj->peer_address != obj->address ? nm_utils_inet4_ntop (nm_platform_ip4_address_get_peer_net (obj), buf2) : "");
+ obj->peer_address != obj->address ? "," : "",
+ obj->peer_address != obj->address ? nm_utils_inet4_ntop (obj->peer_address & nm_utils_ip4_prefix_to_netmask (obj->plen), buf2) : "");
_vt_cmd_plobj_to_string_id (ip6_address, NMPlatformIP6Address, "%d: %s", obj->ifindex, nm_utils_inet6_ntop (&obj->address, buf1));
_vt_cmd_plobj_to_string_id (ip4_route, NMPlatformIP4Route, "%d: %s/%d %d", obj->ifindex, nm_utils_inet4_ntop ( obj->network, buf1), obj->plen, obj->metric);
_vt_cmd_plobj_to_string_id (ip6_route, NMPlatformIP6Route, "%d: %s/%d %d", obj->ifindex, nm_utils_inet6_ntop (&obj->network, buf1), obj->plen, obj->metric);
@@ -664,7 +664,7 @@ _vt_cmd_plobj_id_equal (ip4_address, NMPlatformIP4Address,
&& obj1->address == obj2->address
/* for IPv4 addresses, you can add the same local address with differing peer-adddress
* (IFA_ADDRESS), provided that their net-part differs. */
- && nm_platform_ip4_address_equal_peer_net (obj1, obj2));
+ && ((obj1->peer_address ^ obj2->peer_address) & nm_utils_ip4_prefix_to_netmask (obj1->plen)) == 0);
_vt_cmd_plobj_id_equal (ip6_address, NMPlatformIP6Address,
obj1->ifindex == obj2->ifindex
/* for IPv6 addresses, the prefix length is not part of the primary identifier. */
@@ -719,7 +719,7 @@ _vt_cmd_plobj_id_hash (ip4_address, NMPlatformIP4Address, {
hash = hash * 33 + ((guint) obj->address);
/* for IPv4 we must also consider the net-part of the peer-address (IFA_ADDRESS) */
- hash = hash * 33 + ((guint) (nm_platform_ip4_address_get_peer_net (obj)));
+ hash = hash * 33 + ((guint) (obj->peer_address & nm_utils_ip4_prefix_to_netmask (obj->plen)));
})
_vt_cmd_plobj_id_hash (ip6_address, NMPlatformIP6Address, {
hash = (guint) 2907861637u;
diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c
index e2596786db..df0fffc126 100644
--- a/src/platform/tests/platform.c
+++ b/src/platform/tests/platform.c
@@ -30,6 +30,7 @@
#include "nm-platform.h"
#include "nm-linux-platform.h"
#include "nm-fake-platform.h"
+#include "nm-utils.h"
#define error(...) fprintf (stderr, __VA_ARGS__)
@@ -490,15 +491,17 @@ do_ip4_address_get_all (char **argv)
int ifindex = parse_ifindex (argv[0]);
GArray *addresses;
NMPlatformIP4Address *address;
- char addrstr[INET_ADDRSTRLEN];
int i;
if (ifindex) {
addresses = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
for (i = 0; i < addresses->len; i++) {
address = &g_array_index (addresses, NMPlatformIP4Address, i);
- inet_ntop (AF_INET, &address->address, addrstr, sizeof (addrstr));
- printf ("%s/%d\n", addrstr, address->plen);
+
+ printf ("%s", nm_utils_inet4_ntop (address->address, NULL));
+ if (address->address != address->peer_address)
+ printf (" peer %s", nm_utils_inet4_ntop (address->peer_address, NULL));
+ printf ("/%d\n", address->plen);
}
g_array_unref (addresses);
}
@@ -574,7 +577,7 @@ do_ip4_address_add (char **argv)
guint32 lifetime = strtol (*argv++, NULL, 10);
guint32 preferred = strtol (*argv++, NULL, 10);
- gboolean value = nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, address, plen, 0, lifetime, preferred, NULL);
+ gboolean value = nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, address, plen, address, lifetime, preferred, NULL);
return value;
} else
return FALSE;
@@ -615,11 +618,11 @@ do_ip6_address_add (char **argv)
} else \
return FALSE; \
}
-#define ADDR_CMD(cmdname, ...) ADDR_CMD_FULL (ip4, cmdname, FALSE, 0, ##__VA_ARGS__) ADDR_CMD_FULL (ip6, cmdname, FALSE)
+#define ADDR_CMD(cmdname, ...) ADDR_CMD_FULL (ip4, cmdname, FALSE, address, ##__VA_ARGS__) ADDR_CMD_FULL (ip6, cmdname, FALSE)
#define ADDR_CMD_PRINT(cmdname, ...) ADDR_CMD_FULL (ip4, cmdname, TRUE, ##__VA_ARGS__) ADDR_CMD_FULL (ip6, cmdname, TRUE)
ADDR_CMD (delete)
-ADDR_CMD_PRINT (get, 0)
+ADDR_CMD_PRINT (get, address)
static gboolean
do_ip4_route_get_all (char **argv)
diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
index f37b05ceae..2cdd29622b 100644
--- a/src/platform/tests/test-address.c
+++ b/src/platform/tests/test-address.c
@@ -73,13 +73,13 @@ test_ip4_address_general (void)
inet_pton (AF_INET, IP4_ADDRESS, &addr);
/* Add address */
- g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
- nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, 0, lifetime, preferred, NULL);
- g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
+ g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
+ nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, NULL);
+ g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
accept_signal (address_added);
/* Add address again (aka update) */
- nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, 0, lifetime + 100, preferred + 50, NULL);
+ nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime + 100, preferred + 50, NULL);
accept_signals (address_changed, 0, 1);
/* Test address listing */
@@ -89,16 +89,17 @@ test_ip4_address_general (void)
address = &g_array_index (addresses, NMPlatformIP4Address, 0);
g_assert_cmpint (address->ifindex, ==, ifindex);
g_assert_cmphex (address->address, ==, addr);
+ g_assert_cmphex (address->peer_address, ==, addr);
g_assert_cmpint (address->plen, ==, IP4_PLEN);
g_array_unref (addresses);
/* Remove address */
- nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, 0);
- g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
+ nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr);
+ g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
accept_signal (address_removed);
/* Remove address again */
- nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, 0);
+ nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr);
free_signal (address_added);
free_signal (address_changed);
@@ -173,16 +174,16 @@ test_ip4_address_general_2 (void)
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, DEVICE_IFINDEX, NULL));
/* Add/delete notification */
- nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, 0, lifetime, preferred, NULL);
+ nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, NULL);
accept_signal (address_added);
- g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
- nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, 0);
+ g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
+ nmtstp_ip4_address_del (EX, ifindex, addr, IP4_PLEN, addr);
accept_signal (address_removed);
- g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
+ g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
/* Add/delete conflict */
- nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, 0, lifetime, preferred, NULL);
- g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, 0));
+ nmtstp_ip4_address_add (EX, ifindex, addr, IP4_PLEN, addr, lifetime, preferred, NULL);
+ g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, IP4_PLEN, addr));
accept_signal (address_added);
free_signal (address_added);
@@ -275,6 +276,59 @@ test_ip4_address_peer (void)
/*****************************************************************************/
+static void
+test_ip4_address_peer_zero (void)
+{
+ const int ifindex = DEVICE_IFINDEX;
+ in_addr_t addr, addr_peer;
+ guint32 lifetime = 2000;
+ guint32 preferred = 1000;
+ const int plen = 24;
+ const char *label = NULL;
+ in_addr_t peers[3], r_peers[3];
+ int i;
+ GArray *addrs;
+
+ g_assert (ifindex > 0);
+
+ inet_pton (AF_INET, "192.168.5.2", &addr);
+ inet_pton (AF_INET, "192.168.6.2", &addr_peer);
+ peers[0] = addr;
+ peers[1] = addr_peer;
+ peers[2] = 0;
+
+ g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL));
+
+ nmtst_rand_perm (NULL, r_peers, peers, sizeof (peers[0]), G_N_ELEMENTS (peers));
+ for (i = 0; i < G_N_ELEMENTS (peers); i++) {
+ g_assert (!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
+
+ nmtstp_ip4_address_add (EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, label);
+
+ addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
+ g_assert (addrs);
+ g_assert_cmpint (addrs->len, ==, i + 1);
+ g_array_unref (addrs);
+ }
+
+ if (nmtst_is_debug ())
+ nmtstp_run_command_check ("ip address show dev %s", DEVICE_NAME);
+
+ nmtst_rand_perm (NULL, r_peers, peers, sizeof (peers[0]), G_N_ELEMENTS (peers));
+ for (i = 0; i < G_N_ELEMENTS (peers); i++) {
+ g_assert (nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, addr, plen, r_peers[i]));
+
+ nmtstp_ip4_address_del (EX, ifindex, addr, plen, r_peers[i]);
+
+ addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
+ g_assert (addrs);
+ g_assert_cmpint (addrs->len, ==, G_N_ELEMENTS (peers) - i - 1);
+ g_array_unref (addrs);
+ }
+}
+
+/*****************************************************************************/
+
void
init_tests (int *argc, char ***argv)
{
@@ -342,4 +396,5 @@ setup_tests (void)
_g_test_add_func ("/address/ipv6/general-2", test_ip6_address_general_2);
_g_test_add_func ("/address/ipv4/peer", test_ip4_address_peer);
+ _g_test_add_func ("/address/ipv4/peer/zero", test_ip4_address_peer_zero);
}
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index 4ef6908588..94ce05491d 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -43,7 +43,7 @@ test_cleanup_internal (void)
g_assert (ifindex > 0);
/* Add routes and addresses */
- g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, 0, lifetime, preferred, NULL));
+ g_assert (nm_platform_ip4_address_add (NM_PLATFORM_GET, ifindex, addr4, plen4, addr4, lifetime, preferred, NULL));
g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, addr6, plen6, in6addr_any, lifetime, preferred, flags));
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss));
g_assert (nm_platform_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 7ce4c684d2..98280b4527 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -560,9 +560,6 @@ _ip_address_add (gboolean external_command,
ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
g_assert (ifname);
- if (peer_address == address)
- peer_address = 0;
-
if (lifetime != NM_PLATFORM_LIFETIME_PERMANENT)
s_valid = g_strdup_printf (" valid_lft %d", lifetime);
if (preferred != NM_PLATFORM_LIFETIME_PERMANENT)
@@ -571,11 +568,20 @@ _ip_address_add (gboolean external_command,
s_label = g_strdup_printf ("%s:%s", ifname, label);
if (is_v4) {
+ char s_peer[100];
+
g_assert (flags == 0);
- nmtstp_run_command_check ("ip address change %s%s%s/%d dev %s%s%s%s",
+
+ if ( peer_address->addr4 != address->addr4
+ || nmtst_get_rand_int () % 2) {
+ /* If the peer is the same as the local address, we can omit it. The result should be identical */
+ g_snprintf (s_peer, sizeof (s_peer), " peer %s", nm_utils_inet4_ntop (peer_address->addr4, b2));
+ } else
+ s_peer[0] = '\0';
+
+ nmtstp_run_command_check ("ip address change %s%s/%d dev %s%s%s%s",
nm_utils_inet4_ntop (address->addr4, b1),
- peer_address->addr4 ? " peer " : "",
- peer_address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "",
+ s_peer,
plen,
ifname,
s_valid ?: "",
@@ -637,7 +643,7 @@ _ip_address_add (gboolean external_command,
g_assert (flags == 0);
a = nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4);
if ( a
- && nm_platform_ip4_address_get_peer (a) == (peer_address->addr4 ? peer_address->addr4 : address->addr4)
+ && a->peer_address == peer_address->addr4
&& nmtstp_ip_address_check_lifetime ((NMPlatformIPAddress*) a, -1, lifetime, preferred)
&& strcmp (a->label, label ?: "") == 0)
break;
@@ -729,9 +735,6 @@ _ip_address_del (gboolean external_command,
ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
g_assert (ifname);
- if (peer_address == address)
- peer_address = 0;
-
/* let's wait until we see the address as we added it. */
if (is_v4)
had_address = !!nm_platform_ip4_address_get (NM_PLATFORM_GET, ifindex, address->addr4, plen, peer_address->addr4);
@@ -741,8 +744,8 @@ _ip_address_del (gboolean external_command,
if (is_v4) {
success = nmtstp_run_command ("ip address delete %s%s%s/%d dev %s",
nm_utils_inet4_ntop (address->addr4, b1),
- peer_address->addr4 ? " peer " : "",
- peer_address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "",
+ peer_address->addr4 != address->addr4 ? " peer " : "",
+ peer_address->addr4 != address->addr4 ? nm_utils_inet4_ntop (peer_address->addr4, b2) : "",
plen,
ifname);
} else {
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index 825cb9b496..7695063398 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -470,13 +470,14 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
memset (&address, 0, sizeof (address));
address.plen = 32;
+ if (g_variant_lookup (config_dict, NM_PPP_IP4_CONFIG_ADDRESS, "u", &u32))
+ address.address = u32;
+
if (g_variant_lookup (config_dict, NM_PPP_IP4_CONFIG_GATEWAY, "u", &u32)) {
nm_ip4_config_set_gateway (config, u32);
address.peer_address = u32;
- }
-
- if (g_variant_lookup (config_dict, NM_PPP_IP4_CONFIG_ADDRESS, "u", &u32))
- address.address = u32;
+ } else
+ address.peer_address = address.address;
if (g_variant_lookup (config_dict, NM_PPP_IP4_CONFIG_PREFIX, "u", &u32))
address.plen = u32;
diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c
index abf623b15a..58fe213b5a 100644
--- a/src/tests/test-ip4-config.c
+++ b/src/tests/test-ip4-config.c
@@ -36,6 +36,8 @@ addr_init (NMPlatformIP4Address *a, const char *addr, const char *peer, guint pl
g_assert (inet_pton (AF_INET, addr, (void *) &a->address) == 1);
if (peer)
g_assert (inet_pton (AF_INET, peer, (void *) &a->peer_address) == 1);
+ else
+ a->peer_address = a->address;
a->plen = plen;
}
@@ -152,7 +154,7 @@ test_subtract (void)
test_addr = nm_ip4_config_get_address (dst, 0);
g_assert (test_addr != NULL);
g_assert_cmpuint (test_addr->address, ==, addr_to_num (expected_addr));
- g_assert_cmpuint (test_addr->peer_address, ==, 0);
+ g_assert_cmpuint (test_addr->peer_address, ==, test_addr->address);
g_assert_cmpuint (test_addr->plen, ==, expected_addr_plen);
g_assert_cmpuint (nm_ip4_config_get_gateway (dst), ==, 0);
diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index b3ef60bb56..b3ac9d3e05 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -1409,6 +1409,8 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict)
if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP4_CONFIG_PTP, "u", &u32))
address.peer_address = u32;
+ else
+ address.peer_address = address.address;
if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, "u", &u32))
address.plen = u32;