summaryrefslogtreecommitdiff
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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;