diff options
author | Thomas Haller <thaller@redhat.com> | 2015-10-21 23:17:11 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-11-02 13:57:01 +0100 |
commit | 6c8aa669a4a6be86e29b45fc1a39aadcca9478b0 (patch) | |
tree | 3e19cad9c238c428ecc4469818da34f8f4926781 | |
parent | aa5b89a2ec8db5735925f78f3c91885a513ce51e (diff) | |
download | NetworkManager-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.c | 11 | ||||
-rw-r--r-- | src/devices/wwan/nm-modem-broadband.c | 1 | ||||
-rw-r--r-- | src/dhcp-manager/nm-dhcp-dhclient-utils.c | 1 | ||||
-rw-r--r-- | src/dhcp-manager/nm-dhcp-systemd.c | 1 | ||||
-rw-r--r-- | src/dhcp-manager/nm-dhcp-utils.c | 10 | ||||
-rw-r--r-- | src/dhcp-manager/tests/test-dhcp-dhclient.c | 2 | ||||
-rw-r--r-- | src/dhcp-manager/tests/test-dhcp-utils.c | 2 | ||||
-rw-r--r-- | src/dnsmasq-manager/tests/test-dnsmasq-utils.c | 3 | ||||
-rw-r--r-- | src/nm-ip4-config.c | 14 | ||||
-rw-r--r-- | src/platform/nm-fake-platform.c | 61 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 56 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 54 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 17 | ||||
-rw-r--r-- | src/platform/nmp-object.c | 8 | ||||
-rw-r--r-- | src/platform/tests/platform.c | 15 | ||||
-rw-r--r-- | src/platform/tests/test-address.c | 81 | ||||
-rw-r--r-- | src/platform/tests/test-cleanup.c | 2 | ||||
-rw-r--r-- | src/platform/tests/test-common.c | 27 | ||||
-rw-r--r-- | src/ppp-manager/nm-ppp-manager.c | 9 | ||||
-rw-r--r-- | src/tests/test-ip4-config.c | 4 | ||||
-rw-r--r-- | src/vpn-manager/nm-vpn-connection.c | 2 |
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; |