summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-08-06 15:17:05 +0200
committerThomas Haller <thaller@redhat.com>2021-09-30 09:56:19 +0200
commitd64b4a30d21fa98f6a7d11c28ac21a8f9d8ee299 (patch)
treeddb782113363dea1fa8e0a38e2570c269b98ff24
parentf20431bf89fd00c88659275f69419601cf98cb6b (diff)
downloadNetworkManager-next.tar.gz
core: rework IP configuration in NetworkManager using layer 3 configurationnext
Completely rework IP configuration in the daemon. Use NML3Cfg as layer 3 manager for the IP configuration of an interface. Use NML3ConfigData as pieces of configuration that the various components collect and configure. NMDevice is managing most of the IP configuration at a higher level, that is, it starts DHCP and other IP methods. Rework the state handling there. This is a huge rework of how NetworkManager daemon handles IP configuration. Some fallout is to be expected. It appears the patch deletes many lines of code. That is not accurate, because you also have to count the files `src/core/nm-l3*`, which were unused previously. Co-authored-by: Beniamino Galvani <bgalvani@redhat.com>
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am32
-rw-r--r--WIP.txt13
-rw-r--r--src/core/NetworkManagerUtils.c189
-rw-r--r--src/core/NetworkManagerUtils.h10
-rw-r--r--src/core/README.l3cfg.md332
-rw-r--r--src/core/README.next.ip-config.md59
-rw-r--r--src/core/devices/adsl/nm-device-adsl.c351
-rw-r--r--src/core/devices/bluetooth/nm-device-bt.c92
-rw-r--r--src/core/devices/nm-acd-manager.c497
-rw-r--r--src/core/devices/nm-acd-manager.h34
-rw-r--r--src/core/devices/nm-device-bond.c1
-rw-r--r--src/core/devices/nm-device-dummy.c1
-rw-r--r--src/core/devices/nm-device-ethernet.c439
-rw-r--r--src/core/devices/nm-device-infiniband.c1
-rw-r--r--src/core/devices/nm-device-ip-tunnel.c1
-rw-r--r--src/core/devices/nm-device-macsec.c2
-rw-r--r--src/core/devices/nm-device-macvlan.c1
-rw-r--r--src/core/devices/nm-device-ppp.c236
-rw-r--r--src/core/devices/nm-device-private.h101
-rw-r--r--src/core/devices/nm-device-tun.c1
-rw-r--r--src/core/devices/nm-device-utils.c7
-rw-r--r--src/core/devices/nm-device-utils.h11
-rw-r--r--src/core/devices/nm-device-vlan.c16
-rw-r--r--src/core/devices/nm-device-vxlan.c1
-rw-r--r--src/core/devices/nm-device-wireguard.c77
-rw-r--r--src/core/devices/nm-device-wpan.c1
-rw-r--r--src/core/devices/nm-device.c7365
-rw-r--r--src/core/devices/nm-device.h41
-rw-r--r--src/core/devices/ovs/nm-device-ovs-bridge.c11
-rw-r--r--src/core/devices/ovs/nm-device-ovs-interface.c28
-rw-r--r--src/core/devices/ovs/nm-device-ovs-port.c11
-rw-r--r--src/core/devices/team/nm-device-team.c1
-rw-r--r--src/core/devices/tests/meson.build1
-rw-r--r--src/core/devices/tests/test-acd.c259
-rw-r--r--src/core/devices/wifi/nm-device-iwd.c6
-rw-r--r--src/core/devices/wifi/nm-device-wifi-p2p.c47
-rw-r--r--src/core/devices/wifi/nm-device-wifi.c161
-rw-r--r--src/core/devices/wwan/libnm-wwan.ver1
-rw-r--r--src/core/devices/wwan/nm-device-modem.c196
-rw-r--r--src/core/devices/wwan/nm-modem-broadband.c260
-rw-r--r--src/core/devices/wwan/nm-modem-ofono.c121
-rw-r--r--src/core/devices/wwan/nm-modem.c377
-rw-r--r--src/core/devices/wwan/nm-modem.h42
-rw-r--r--src/core/dhcp/README.next.md103
-rw-r--r--src/core/dhcp/nm-dhcp-client.c1087
-rw-r--r--src/core/dhcp/nm-dhcp-client.h259
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient-utils.c1
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient.c145
-rw-r--r--src/core/dhcp/nm-dhcp-dhcpcanon.c2
-rw-r--r--src/core/dhcp/nm-dhcp-dhcpcd.c22
-rw-r--r--src/core/dhcp/nm-dhcp-manager.c321
-rw-r--r--src/core/dhcp/nm-dhcp-manager.h48
-rw-r--r--src/core/dhcp/nm-dhcp-nettools.c338
-rw-r--r--src/core/dhcp/nm-dhcp-systemd.c334
-rw-r--r--src/core/dhcp/nm-dhcp-utils.c299
-rw-r--r--src/core/dhcp/nm-dhcp-utils.h31
-rw-r--r--src/core/dhcp/tests/test-dhcp-dhclient.c1
-rw-r--r--src/core/dhcp/tests/test-dhcp-utils.c567
-rw-r--r--src/core/dns/nm-dns-dnsmasq.c33
-rw-r--r--src/core/dns/nm-dns-manager.c594
-rw-r--r--src/core/dns/nm-dns-manager.h18
-rw-r--r--src/core/dns/nm-dns-systemd-resolved.c64
-rw-r--r--src/core/dnsmasq/nm-dnsmasq-manager.c51
-rw-r--r--src/core/dnsmasq/nm-dnsmasq-manager.h10
-rw-r--r--src/core/meson.build4
-rw-r--r--src/core/ndisc/nm-fake-ndisc.c38
-rw-r--r--src/core/ndisc/nm-fake-ndisc.h2
-rw-r--r--src/core/ndisc/nm-lndp-ndisc.c92
-rw-r--r--src/core/ndisc/nm-lndp-ndisc.h13
-rw-r--r--src/core/ndisc/nm-ndisc.c495
-rw-r--r--src/core/ndisc/nm-ndisc.h39
-rw-r--r--src/core/ndisc/tests/test-ndisc-fake.c70
-rw-r--r--src/core/ndisc/tests/test-ndisc-linux.c53
-rw-r--r--src/core/nm-act-request.c38
-rw-r--r--src/core/nm-act-request.h8
-rw-r--r--src/core/nm-active-connection.h3
-rw-r--r--src/core/nm-config-data.c84
-rw-r--r--src/core/nm-config-data.h6
-rw-r--r--src/core/nm-connectivity.c1
-rw-r--r--src/core/nm-dhcp-config.c99
-rw-r--r--src/core/nm-dhcp-config.h5
-rw-r--r--src/core/nm-dispatcher.c181
-rw-r--r--src/core/nm-dispatcher.h8
-rw-r--r--src/core/nm-iface-helper.c13
-rw-r--r--src/core/nm-ip-config.c774
-rw-r--r--src/core/nm-ip-config.h55
-rw-r--r--src/core/nm-ip4-config.c3303
-rw-r--r--src/core/nm-ip4-config.h670
-rw-r--r--src/core/nm-ip6-config.c2675
-rw-r--r--src/core/nm-ip6-config.h205
-rw-r--r--src/core/nm-manager.c8
-rw-r--r--src/core/nm-pacrunner-manager.c101
-rw-r--r--src/core/nm-pacrunner-manager.h7
-rw-r--r--src/core/nm-policy.c311
-rw-r--r--src/core/nm-proxy-config.c172
-rw-r--r--src/core/nm-proxy-config.h41
-rw-r--r--src/core/nm-types.h3
-rw-r--r--src/core/platform/nm-fake-platform.c2
-rw-r--r--src/core/platform/tests/test-route.c104
-rw-r--r--src/core/ppp/nm-ppp-manager-call.c18
-rw-r--r--src/core/ppp/nm-ppp-manager-call.h6
-rw-r--r--src/core/ppp/nm-ppp-manager.c194
-rw-r--r--src/core/ppp/nm-ppp-manager.h3
-rw-r--r--src/core/ppp/nm-ppp-plugin-api.h6
-rw-r--r--src/core/tests/meson.build2
-rw-r--r--src/core/tests/test-ip4-config.c380
-rw-r--r--src/core/tests/test-ip6-config.c538
-rw-r--r--src/core/vpn/nm-vpn-connection.c716
-rw-r--r--src/core/vpn/nm-vpn-connection.h4
-rw-r--r--src/libnm-platform/nm-linux-platform.c1
-rw-r--r--src/libnm-platform/nm-platform.c41
-rw-r--r--src/libnm-platform/nm-platform.h12
-rw-r--r--src/libnm-systemd-core/meson.build2
-rw-r--r--src/libnm-systemd-core/nm-sd.h1
-rwxr-xr-xtools/run-nm-test.sh1
116 files changed, 8752 insertions, 18620 deletions
diff --git a/.gitignore b/.gitignore
index 25c60b1270..40d74286fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -240,7 +240,6 @@ test-*.trs
/src/core/NetworkManager-all-sym
/src/core/NetworkManager.ver
/src/core/devices/bluetooth/tests/nm-bt-test
-/src/core/devices/tests/test-acd
/src/core/devices/tests/test-lldp
/src/core/devices/wifi/tests/test-devices-wifi
/src/core/devices/wwan/tests/test-service-providers
@@ -406,6 +405,7 @@ test-*.trs
/src/NetworkManager
/src/NetworkManager-all-sym
/src/NetworkManager.ver
+/src/core/devices/tests/test-acd
/src/core/initrd/nm-initrd-generator
/src/core/initrd/tests/test-cmdline-reader
/src/core/initrd/tests/test-dt-reader
diff --git a/Makefile.am b/Makefile.am
index 05406d674e..62b39ad87c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2318,8 +2318,6 @@ src_libnm_systemd_core_libnm_systemd_core_la_SOURCES = \
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c \
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c \
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c \
- src/libnm-systemd-core/src/libsystemd-network/sd-ipv4acd.c \
- src/libnm-systemd-core/src/libsystemd-network/sd-ipv4ll.c \
src/libnm-systemd-core/src/libsystemd-network/sd-lldp.c \
src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h \
src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c \
@@ -2337,8 +2335,6 @@ src_libnm_systemd_core_libnm_systemd_core_la_SOURCES = \
src/libnm-systemd-core/src/systemd/sd-dhcp6-option.h \
src/libnm-systemd-core/src/systemd/sd-event.h \
src/libnm-systemd-core/src/systemd/sd-id128.h \
- src/libnm-systemd-core/src/systemd/sd-ipv4acd.h \
- src/libnm-systemd-core/src/systemd/sd-ipv4ll.h \
src/libnm-systemd-core/src/systemd/sd-lldp.h \
src/libnm-systemd-core/src/systemd/sd-ndisc.h \
$(NULL)
@@ -2388,10 +2384,6 @@ src_core_libNetworkManagerBase_la_SOURCES = \
src/core/nm-l3cfg.h \
src/core/nm-ip-config.c \
src/core/nm-ip-config.h \
- src/core/nm-ip4-config.c \
- src/core/nm-ip4-config.h \
- src/core/nm-ip6-config.c \
- src/core/nm-ip6-config.h \
\
src/core/dhcp/nm-dhcp-client.c \
src/core/dhcp/nm-dhcp-client.h \
@@ -2430,8 +2422,6 @@ src_core_libNetworkManager_la_SOURCES = \
src/core/nm-checkpoint-manager.c \
src/core/nm-checkpoint-manager.h \
\
- src/core/devices/nm-acd-manager.c \
- src/core/devices/nm-acd-manager.h \
src/core/devices/nm-lldp-listener.c \
src/core/devices/nm-lldp-listener.h \
src/core/devices/nm-device-utils.c \
@@ -2580,8 +2570,6 @@ src_core_libNetworkManager_la_SOURCES = \
src/core/nm-firewall-utils.h \
src/core/nm-firewalld-manager.c \
src/core/nm-firewalld-manager.h \
- src/core/nm-proxy-config.c \
- src/core/nm-proxy-config.h \
src/core/nm-auth-manager.c \
src/core/nm-auth-manager.h \
src/core/nm-auth-utils.c \
@@ -4269,20 +4257,14 @@ src_core_devices_tests_ldflags = \
check_programs += \
src/core/devices/tests/test-lldp \
- src/core/devices/tests/test-acd
+ $(NULL)
src_core_devices_tests_test_lldp_CPPFLAGS = $(src_core_cppflags_test)
src_core_devices_tests_test_lldp_LDFLAGS = $(src_core_devices_tests_ldflags)
src_core_devices_tests_test_lldp_LDADD = \
src/core/libNetworkManagerTest.la
-src_core_devices_tests_test_acd_CPPFLAGS = $(src_core_cppflags_test)
-src_core_devices_tests_test_acd_LDFLAGS = $(src_core_devices_tests_ldflags)
-src_core_devices_tests_test_acd_LDADD = \
- src/core/libNetworkManagerTest.la
-
$(src_core_devices_tests_test_lldp_OBJECTS): $(src_libnm_core_public_mkenums_h)
-$(src_core_devices_tests_test_acd_OBJECTS): $(src_libnm_core_public_mkenums_h)
EXTRA_DIST += \
src/core/devices/tests/meson.build
@@ -4385,22 +4367,12 @@ check_programs += \
src/core/tests/test-core \
src/core/tests/test-core-with-expect \
src/core/tests/test-dcb \
- src/core/tests/test-ip4-config \
- src/core/tests/test-ip6-config \
src/core/tests/test-l3cfg \
src/core/tests/test-systemd \
src/core/tests/test-utils \
src/core/tests/test-wired-defname \
$(NULL)
-src_core_tests_test_ip4_config_CPPFLAGS = $(src_core_cppflags_test)
-src_core_tests_test_ip4_config_LDFLAGS = $(src_core_tests_ldflags)
-src_core_tests_test_ip4_config_LDADD = $(src_core_tests_ldadd)
-
-src_core_tests_test_ip6_config_CPPFLAGS = $(src_core_cppflags_test)
-src_core_tests_test_ip6_config_LDFLAGS = $(src_core_tests_ldflags)
-src_core_tests_test_ip6_config_LDADD = $(src_core_tests_ldadd)
-
src_core_tests_test_dcb_CPPFLAGS = $(src_core_cppflags_test)
src_core_tests_test_dcb_LDFLAGS = $(src_core_tests_ldflags)
src_core_tests_test_dcb_LDADD = $(src_core_tests_ldadd)
@@ -4428,8 +4400,6 @@ src_core_tests_test_l3cfg_LDADD = $(src_core_tests_ldadd)
$(src_core_tests_test_core_OBJECTS): $(src_libnm_core_public_mkenums_h)
$(src_core_tests_test_core_with_expect_OBJECTS): $(src_libnm_core_public_mkenums_h)
$(src_core_tests_test_dcb_OBJECTS): $(src_libnm_core_public_mkenums_h)
-$(src_core_tests_test_ip4_config_OBJECTS): $(src_libnm_core_public_mkenums_h)
-$(src_core_tests_test_ip6_config_OBJECTS): $(src_libnm_core_public_mkenums_h)
$(src_core_tests_test_l3cfg_OBJECTS): $(src_libnm_core_public_mkenums_h)
$(src_core_tests_test_utils_OBJECTS): $(src_libnm_core_public_mkenums_h)
$(src_core_tests_test_wired_defname_OBJECTS): $(src_libnm_core_public_mkenums_h)
diff --git a/WIP.txt b/WIP.txt
new file mode 100644
index 0000000000..688cb6785f
--- /dev/null
+++ b/WIP.txt
@@ -0,0 +1,13 @@
+The following files have changes since the last rebase,
+that need re-review. They probably also don't compile
+and are incomplete:
+
+ > src/core/devices/nm-device.c
+ > src/core/devices/nm-device.h
+ > src/core/nm-iface-helper.c
+ > src/core/nm-ip-config.c
+ > src/core/nm-ip4-config.h
+ > src/core/nm-ip6-config.h
+ > src/core/nm-manager.c
+ > src/core/nm-policy.c
+ > src/core/vpn/nm-vpn-connection.c
diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c
index 0da8e0a949..49d011b3d0 100644
--- a/src/core/NetworkManagerUtils.c
+++ b/src/core/NetworkManagerUtils.c
@@ -1298,7 +1298,7 @@ void
nm_utils_ip_route_attribute_to_platform(int addr_family,
NMIPRoute * s_route,
NMPlatformIPRoute *r,
- guint32 route_table)
+ gint64 route_table)
{
GVariant * variant;
guint32 table;
@@ -1310,6 +1310,8 @@ nm_utils_ip_route_attribute_to_platform(int addr_family,
nm_assert(s_route);
nm_assert_addr_family(addr_family);
nm_assert(r);
+ nm_assert(route_table >= -1);
+ nm_assert(route_table <= (gint64) G_MAXUINT32);
#define GET_ATTR(name, dst, variant_type, type, dflt) \
G_STMT_START \
@@ -1336,10 +1338,16 @@ nm_utils_ip_route_attribute_to_platform(int addr_family,
GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0);
- if (!table && r->type_coerced == nm_platform_route_type_coerce(RTN_LOCAL))
+ if (table != 0)
+ r->table_coerced = nm_platform_route_table_coerce(table);
+ else if (r->type_coerced == nm_platform_route_type_coerce(RTN_LOCAL))
r->table_coerced = nm_platform_route_table_coerce(RT_TABLE_LOCAL);
+ else if (route_table == 0)
+ r->table_coerced = nm_platform_route_table_coerce(RT_TABLE_MAIN);
+ else if (route_table > 0)
+ r->table_coerced = nm_platform_route_table_coerce(route_table);
else
- r->table_coerced = nm_platform_route_table_coerce(table ?: (route_table ?: RT_TABLE_MAIN));
+ r->table_any = TRUE;
if (NM_IS_IPv4(addr_family)) {
guint8 scope;
@@ -1395,39 +1403,20 @@ nm_utils_ip_route_attribute_to_platform(int addr_family,
/*****************************************************************************/
-static int
-_addresses_sort_cmp_4(gconstpointer a, gconstpointer b, gpointer user_data)
-{
- return nm_platform_ip4_address_pretty_sort_cmp(
- NMP_OBJECT_CAST_IP4_ADDRESS(*((const NMPObject **) a)),
- NMP_OBJECT_CAST_IP4_ADDRESS(*((const NMPObject **) b)));
-}
-
-static int
-_addresses_sort_cmp_6(gconstpointer a, gconstpointer b, gpointer user_data)
-{
- return nm_platform_ip6_address_pretty_sort_cmp(
- NMP_OBJECT_CAST_IP6_ADDRESS(*((const NMPObject **) a)),
- NMP_OBJECT_CAST_IP6_ADDRESS(*((const NMPObject **) b)),
- (((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT(user_data))
- == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
-}
-
void
nm_utils_ip_addresses_to_dbus(int addr_family,
const NMDedupMultiHeadEntry *head_entry,
const NMPObject * best_default_route,
- NMSettingIP6ConfigPrivacy ipv6_privacy,
GVariant ** out_address_data,
GVariant ** out_addresses)
{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- GVariantBuilder builder_data;
- GVariantBuilder builder_legacy;
- char addr_str[NM_UTILS_INET_ADDRSTRLEN];
- gs_free const NMPObject **addresses = NULL;
- guint naddr;
- guint i;
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ GVariantBuilder builder_data;
+ GVariantBuilder builder_legacy;
+ char addr_str[NM_UTILS_INET_ADDRSTRLEN];
+ NMDedupMultiIter iter;
+ const NMPObject *obj;
+ guint i;
nm_assert_addr_family(addr_family);
@@ -1443,19 +1432,11 @@ nm_utils_ip_addresses_to_dbus(int addr_family,
if (!head_entry)
goto out;
- addresses =
- (const NMPObject **) nm_dedup_multi_objs_to_array_head(head_entry, NULL, NULL, &naddr);
-
- nm_assert(addresses && naddr);
-
- g_qsort_with_data(addresses,
- naddr,
- sizeof(addresses[0]),
- IS_IPv4 ? _addresses_sort_cmp_4 : _addresses_sort_cmp_6,
- GINT_TO_POINTER(ipv6_privacy));
-
- for (i = 0; i < naddr; i++) {
- const NMPlatformIPXAddress *address = NMP_OBJECT_CAST_IPX_ADDRESS(addresses[i]);
+ i = 0;
+ nm_dedup_multi_iter_init(&iter, head_entry);
+ while (
+ nm_platform_dedup_multi_iter_next_obj(&iter, &obj, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4))) {
+ const NMPlatformIPXAddress *address = NMP_OBJECT_CAST_IPX_ADDRESS(obj);
if (out_address_data) {
GVariantBuilder addr_builder;
@@ -1527,6 +1508,8 @@ nm_utils_ip_addresses_to_dbus(int addr_family,
: &in6addr_any));
}
}
+
+ i++;
}
out:
@@ -1654,6 +1637,128 @@ nm_utils_ip_routes_to_dbus(int addr_family,
/*****************************************************************************/
+NMSetting *
+nm_utils_platform_capture_ip_setting(NMPlatform *platform,
+ int addr_family,
+ int ifindex,
+ gboolean maybe_ipv6_disabled)
+{
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ gs_unref_object NMSettingIPConfig *s_ip = NULL;
+ NMPLookup lookup;
+ NMDedupMultiIter iter;
+ const NMPObject * obj;
+ const char * method = NULL;
+ char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ const NMPlatformIPXRoute * best_default_route = NULL;
+
+ s_ip =
+ NM_SETTING_IP_CONFIG(IS_IPv4 ? nm_setting_ip4_config_new() : nm_setting_ip6_config_new());
+
+ if (ifindex <= 0 || !nm_platform_link_get(platform, ifindex)) {
+ g_object_set(s_ip,
+ NM_SETTING_IP_CONFIG_METHOD,
+ IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_DISABLED
+ : NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+ NULL);
+ return NM_SETTING(g_steal_pointer(&s_ip));
+ }
+
+ nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex);
+ nm_platform_iter_obj_for_each (&iter, platform, &lookup, &obj) {
+ const NMPlatformIPXAddress *address = NMP_OBJECT_CAST_IPX_ADDRESS(obj);
+ nm_auto_unref_ip_address NMIPAddress *s_addr = NULL;
+
+ if (!IS_IPv4) {
+ /* Ignore link-local address. */
+ if (IN6_IS_ADDR_LINKLOCAL(address->ax.address_ptr)) {
+ if (!method)
+ method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
+ continue;
+ }
+ }
+
+ /* Detect dynamic address */
+ if (address->ax.lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
+ method =
+ IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_AUTO : NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+ continue;
+ }
+
+ /* Static address found. */
+ if (IS_IPv4) {
+ if (!method)
+ method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+ } else {
+ if (NM_IN_STRSET(method, NULL, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
+ method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+ }
+
+ s_addr =
+ nm_ip_address_new_binary(addr_family, address->ax.address_ptr, address->ax.plen, NULL);
+
+ if (IS_IPv4) {
+ if (address->a4.label[0]) {
+ nm_ip_address_set_attribute(s_addr,
+ NM_IP_ADDRESS_ATTRIBUTE_LABEL,
+ g_variant_new_string(address->a4.label));
+ }
+ }
+
+ nm_setting_ip_config_add_address(s_ip, s_addr);
+ }
+
+ if (!method) {
+ /* Use 'disabled/ignore' if the method wasn't previously set */
+ if (IS_IPv4)
+ method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
+ else
+ method = maybe_ipv6_disabled ? NM_SETTING_IP6_CONFIG_METHOD_DISABLED
+ : NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
+ }
+ g_object_set(s_ip, NM_SETTING_IP_CONFIG_METHOD, method, NULL);
+
+ nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4), ifindex);
+ nm_platform_iter_obj_for_each (&iter, platform, &lookup, &obj) {
+ const NMPlatformIPXRoute *route = NMP_OBJECT_CAST_IPX_ROUTE(obj);
+ nm_auto_unref_ip_route NMIPRoute *s_route = NULL;
+
+ if (!IS_IPv4) {
+ /* Ignore link-local route. */
+ if (IN6_IS_ADDR_LINKLOCAL(route->rx.network_ptr))
+ continue;
+ }
+
+ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) {
+ if (!best_default_route)
+ best_default_route = route;
+ continue;
+ }
+
+ s_route = nm_ip_route_new_binary(addr_family,
+ route->rx.network_ptr,
+ route->rx.plen,
+ nm_platform_ip_route_get_gateway(addr_family, &route->rx),
+ route->rx.metric,
+ NULL);
+ nm_setting_ip_config_add_route(s_ip, s_route);
+ }
+
+ if (best_default_route && nm_setting_ip_config_get_num_addresses(s_ip) > 0) {
+ g_object_set(s_ip,
+ NM_SETTING_IP_CONFIG_GATEWAY,
+ nm_utils_inet_ntop(
+ addr_family,
+ nm_platform_ip_route_get_gateway(addr_family, &best_default_route->rx),
+ sbuf),
+ NULL);
+ }
+
+ return NM_SETTING(g_steal_pointer(&s_ip));
+}
+
+/*****************************************************************************/
+
/* Singleton NMPlatform subclass instance and cached class object */
NM_DEFINE_SINGLETON_INSTANCE(NMPlatform);
diff --git a/src/core/NetworkManagerUtils.h b/src/core/NetworkManagerUtils.h
index a2ac732e83..52b870e8a9 100644
--- a/src/core/NetworkManagerUtils.h
+++ b/src/core/NetworkManagerUtils.h
@@ -195,12 +195,11 @@ nm_utils_tfilters_from_tc_setting(NMPlatform *platform, NMSettingTCConfig *s_tc,
void nm_utils_ip_route_attribute_to_platform(int addr_family,
NMIPRoute * s_route,
NMPlatformIPRoute *r,
- guint32 route_table);
+ gint64 route_table);
void nm_utils_ip_addresses_to_dbus(int addr_family,
const NMDedupMultiHeadEntry *head_entry,
const NMPObject * best_default_route,
- NMSettingIP6ConfigPrivacy ipv6_privacy,
GVariant ** out_address_data,
GVariant ** out_addresses);
@@ -271,6 +270,13 @@ NM_AUTO_DEFINE_FCN(NMDhcpLease *, _nm_auto_unref_dhcplease, nm_dhcp_lease_unref)
/*****************************************************************************/
+NMSetting *nm_utils_platform_capture_ip_setting(NMPlatform *platform,
+ int addr_family,
+ int ifindex,
+ gboolean maybe_ipv6_disabled);
+
+/*****************************************************************************/
+
void nm_platform_setup(NMPlatform *instance);
NMPlatform *nm_platform_get(void);
diff --git a/src/core/README.l3cfg.md b/src/core/README.l3cfg.md
new file mode 100644
index 0000000000..100ce012ea
--- /dev/null
+++ b/src/core/README.l3cfg.md
@@ -0,0 +1,332 @@
+L3Cfg Rework
+============
+
+NMDevice is complex. Together with NMManager, NMDevice does too much.
+
+The goal is to rework the IP configuration (Layer 3) to be a more separate
+part of the code that is better maintainable, easier to understand and
+extend and more correct.
+
+Current Situation
+-----------------
+
+- [NMManager](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-manager.c):
+ this is the main object (a singleton) that drives most things.
+ Among many other things, it creates NMDevice instances and coordinates.
+
+- [NMDevice](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c):
+ this represents a device. This is a subclass of NMDBusObject,
+ it is thus directly exported on D-Bus (as D-Bus objects like
+ `/org/freedesktop/NetworkManager/Devices/1`).
+ It also manages all aspects of the device. It has an overall state
+ (`NM_DEVICE_STATE`) but lots of more specific states (e.g. current state
+ of DHCP configuration). As always, the hardest part in programming are
+ stateful objects, and NMDevice has *a lot* of state. The code is huge and
+ hard to understand and the class has (too) many responsibilities. \
+ \
+ NMDevice also has subclasses, which are determined based on the "device type". That
+ means, there are subclasses like NMDeviceEthernet and NMDeviceBridge. As such, the
+ subclasses also export additional D-Bus interfaces. These subclasses also handle
+ the Layer 2 specific aspects of the device. For this aspect, delegation probably
+ would have been a better choice. On the other hand, IP configuration is almost entirely
+ managed by the parent class. Which is good, because the IP configuration is common to all
+ device types, but is bad because NMDevice already does so many things.
+
+- [NMIP4Config](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-ip4-config.c) (and NMIP6Config):
+ these are also subclasses of NMDBusObject
+ and exported on D-Bus on paths like `/org/freedesktop/NetworkManager/IP4Config/1`.
+ The device's `IP4Config` property refers to these objects. They contain
+ the runtime IP information of that device. I don't think these objects
+ should exist on the D-Bus API, as NMDevice could directly expose these properties.
+ But for historic reasons, such is our D-Bus API.
+ Other than that, NMIP4Config objects are also used internally for tracking
+ IP configuration. For example, [when](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/dhcp/nm-dhcp-nettools.c#L563)
+ we receive a DHCP lease, we construct a NMIP4Config object with the addresses, DNS settings,
+ and so on. These
+ instances are then [tracked by](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L519)
+ NMDevice, and [merged](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L8928)
+ into an instance that is then exposed on D-Bus. As such, this class has two
+ mostly independent purposes.
+
+- [NMDhcpClient](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/dhcp/nm-dhcp-client.c):
+ our DHCP "library". It's a simple object with a clear API that
+ abstracts most of the complexity of handling DHCP. But still, NMDevice
+ needs to drive the DHCP client instance. Meaning, it needs to create (start) and stop
+ them and hook up signals for changes (new lease) and timeout. This is mostly
+ fine and unavoidable. The point is that while specific tasks are well abstracted
+ (like the details of DHCP), there is still some state in NMDevice that is related
+ to manage these tasks. DHCP is one of many such tasks, like also
+ link local addresses, SLAAC or LLDP.
+ This leads to the increased complexity of NMDevice, which manages a large variety
+ of such tasks.
+
+### Problems:
+
+1. first the sheer code size of [nm-device.c](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L19030).
+ It's hard to understand and maintain, and this results in misbehaviours. Also, features that should be easy to implement
+ are not. Also, there are inefficiencies that are hard to fix.
+
+2. NMDevice and NMIP4Config are both exported on D-Bus while having other responsibilities.
+ Being subclasses of NMDBusObject, they are glued to the D-Bus API. For example, NMIP4Config is
+ also used for other purposes (for tracking IP configuration internally).
+
+3. NMDevice simply does too much. IP configuration should be a separate, encapsulated
+ API to make allow NMDevice to be smaller and the IP configuration part better
+ testable, understandable and smaller too.
+
+4. in the current model, NMDevice can be related to zero, one or two ifindexes. For example,
+ for ethernet devices, there is commonly only one actual netdev device (and one ifindex).
+ For OVS devices, there is no ifindex. For NMDeviceModem or NMDeviceBluetooth there is
+ a NMDevice instance that has initially no ifindex (it represents the tty serial port
+ or the bluetooth device) but during activation it gets and ip ifindex. With PPPoE,
+ the ethernet device can even have two ifindexes (one for the underlying ethernet and
+ one for the PPP device). That is all utterly confusing, inconsistent and limited.
+ For example, not all interfaces you see in `ip link` can be found in the D-Bus API.
+ The D-Bus API also does not give access to the ifindex (which is the real identifier
+ for a netdev devices). It only exposes the IpInterface name. That should be improved too,
+ but even such seemingly simple things are not done for years, because it's not trivially
+ clear what the right ifindex is.
+ Also a device instance on D-Bus significantly changes its meaning when it activates/deactivates
+ and it starts/stops being responsible for an ifindex.
+ In the future there should be devices that represent exactly one netdev device (an ifindex)
+ and devices that don't have an ifindex. That is follow up work and hinted by
+ [rhbz#1066703](https://bugzilla.redhat.com/show_bug.cgi?id=1066703). But simplifying
+ the IP configuration is a requisite before addressing that rework.
+ With this we will have controller and controlled devices. That means, a controller devices
+ (that for example represents a bluetooth device) will need to configure IP address on the
+ controlled IP device. That would be doable by injecting the IP config on that device,
+ but as the device already does so much, it would be better if this would be a separate
+ IP configuration manager for that ifindex.
+
+5. NMIP4Config exports properties on D-Bus like [AddressData](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/introspection/org.freedesktop.NetworkManager.IP4Config.xml#L26).
+ which are the currently configured IP addresses. These should be directly obtained
+ from the NMPlatform cache, which contains the correct list of addresses as kernel
+ exposes them via rtnetlink. Instead, whenever there are changes in platform we
+ [generate](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L14223)
+ an NMIP4Config instance, then we merge, intersect and subtract this captured information
+ with the IP configs we want to configure. Finally we merge them together again
+ and sync the result to platform. This is bad, wrong and inefficient.
+ We must not mix "what is configured" with "what we want to configure". The current
+ approach also re-generates these IP config instance whenever something in platform changes.
+ That does not scale. If we have any hope to handle thousands of routes, this needs to change.
+
+6. The NMIP4Config objects are mutable, and they are heavily mutated. When we create an NMIP4Config
+ instance that represent a DHCP lease, we will [subtract](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L14236)
+ addresses that were externally removed. That is wrong, because during a reapply we
+ will need to know these addresses again. The solution for that is not to mutate this
+ data, but track whether IP addresses are removed separately.
+
+7. NMDevice also does ACD, but it can only do it for addresses received via DHCP.
+ It implicitly also does ACD for IPv4LL, but that is via using the n_ipv4ll library.
+ It would be good to have an option that we can configure IPv4LL for any address.
+ Also, if you manually configure an address like 192.168.2.5 (for which we don't do
+ ACD) and the same address is obtained via DHCP, then doing ACD for the address is wrong.
+ There needs to be link-wide view of the addresses, and not only looking at individual
+ addresses when deciding to do ACD.
+
+8. As IP configuration is done by NMDevice, VPN connections have limited capabilities
+ in this regard.
+ When a VPN has IP addresses, then it injects them into NMDevice by
+ [providing](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L13696)
+ an NMIP4Config. However, that means VPNs cannot do DHCP or IPv4LL, because it can
+ only inject known configuration. That would be very useful for example with a tap
+ device with openvpn. The real problem here is that NMVpnConnection are
+ treated special, when they should be more like devices. That should be reworked in the future,
+ by reworking VPN plugins. Regardless, having IP configuration handled by NMDevice is limiting.
+
+9. NetworkManager currently supports `ipv4.method` which can be "manual", "disabled" or
+ "auto". This scheme does not allow for example to enable IPv4LL together with DHCPv4.
+ As a special case, you can configure `ipv4.method=auto` together with static
+ addresses in `ipv4.addresses`, so combining DHCP and static addressing works. But in general,
+ this scheme is limited. In the future we should have more flexible schemes, where
+ addressing methods can be independently enabled or disabled. Also, we currently
+ have `ipv4.may-fail`, but that is limited as well. For example,
+ `ipv4.may-fail=yes` and `ipv6.may-fail=yes` still means that at least one of the
+ address families must succeed. That makes sense for certain use cases, but it
+ means, you cannot have truly best-effort, opportunistic DHCP with this way.
+ As workaround for that there is `ipv4.dhcp-timeout=infinity`. In
+ general it is not only useful to enable methods independently, we also configure
+ independently whether they are required or optional (and possibly, that they are optional
+ but at least one of several optional methods must succeed). Anyway. The point
+ is there is a need to make IP configuration more flexible. Currently it is not.
+ Such a seemingly simple extension would be surprisingly difficult to implement
+ because [the code](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L6616) is
+ all over the place. The way how NMDevice tracks the overall activation state is
+ hard to understand. This should be improved and possibly could be improved in a
+ smaller refactoring effort. But instead of a smaller effort, we will use the big hammer
+ with L3Cfg rework.
+
+10. There are two classes NMIP4Config and NMIP6Config. Handling both address families is
+ commonly similar, so there is lot of similar code in both. They should be unified
+ so that similar code can handle both address families.
+
+
+Solution and Future
+-------------------
+
+NML3Cfg work is supposed to simplify some part of NMDevice: the part related to
+IP configuration. This is a huge rework of a core part of NetworkManager. Arguably,
+some parts maybe could be done more evolutionary, but the fundamental problems require
+to rip out NMIP4Config and replace it by something better. Doing that is a large rework
+that changes NMDevice heavily. That is also the opportunity to get the smaller issues
+right.
+
+There is already a new class [NML3Cfg](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.h#L141)
+(currently unused). An NML3Cfg instance is responsible for handling IP configuration
+of an ifindex. Consequently, we can ask NMNetns to [get](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-netns.c#L142)
+(or create) a NML3Cfg instance for an ifindex.
+The idea is that there can be multiple users (NMDevice and NMVpnConnection and future controller devices)
+that use the same NML3Cfg instance. Especially with a future rework of NMDevice where
+a NMDevice only manages one ifindex (or none), there is a need that multiple
+devices manage the IP configuration on the same device. Independent users can cooperate
+to configure IP configuration on the same device. Already now with Libreswan VPN, where the VPN "injects"
+its NMIP4Config in NMDevice. Or with PPPoE, where the NMDeviceEthernet is both about IP configuration
+for the PPPoE device.
+
+There is also a new class [NML3ConfigData](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3-config-data.h).
+This replaces some aspect of NMIP4Config/NMIP6Config. A NML3ConfigData object is immutable and has no real logic
+(or state). It has some "logic", like comparing two NML3ConfigData instances, logging it, or merging two (immutable)
+instances into a new instance. But as the class is immutable, that logic is rather simple. This class is
+used to track information. As it's immutable, anybody who is interested can keep a reference
+for it's own purpose. For example, NMDhcpClient will generate a NML3ConfigData with the information
+of the lease. It may keep the reference, but it will also tell NMDevice about it. The NMDevice
+will then itself tell NML3Cfg to accept this configuration. This works by calling
+[add()/remove()](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L2654).
+One NML3ConfigData can also track both IPv4 and IPv6 information. It's a general set of IP related
+configuration, that has some address specific properties. Those are then duplicated for both address
+families and implemented in a way to minimize code duplication and encourage to treat them the same.
+As this replaces an aspect of NMIP4Config, NMIP4Config can focus on it's other purpose: to expose data on D-Bus.
+
+What NML3Cfg then does, is to merge all NML3ConfigData, and "commit" it to platform. Thereby it knows
+which addresses it configured the last time (if they no longer are to be configured, they must be removed).
+This is done [here](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L3442).
+
+As independent users should be able to cooperate, it is not appropriate that they call "commit".
+Instead, they set a commit type ([here](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L3476),
+and whenever something changes, NML3Cfg knows the aggregated commit type. That is necessary
+because when we activate a device, we may want to preserve the existing IP configuration (e.g. after
+a restart of NetworkManager). During that time is the NML3Cfg instance set to a reduced commit
+mode (ASSUME).
+
+NML3Cfg will also handle IPv4 ACD. Any user of NML3Cfg registers/unregisters NML3ConfigData instances
+that should be configured. Thereby they also say whether ACD should be done for the IPv4 addresses.
+NML3Cfg then keeps state for each IPv4 address, whether ACD should be performed, and whether the
+address is ready to be configured. NML3Cfg does not do DHCP or similar. That is still the responsibility
+of NMDevice to run a NMDhcpClient. But it does run ACD, because whether to perform ACD on an address
+requires a holistic view of all addresses of that interface. For example, if you configure a static
+IP address 192.168.2.5 (with ACD disabled) and you also get the same address via DHCP, then ACD should
+not performed for that address (even if the user configured ACD with DHCP). Of course, that is a very
+unlikely example. More likely is that NetworkManager is restarted and it leaves the addresses (that passed
+ACD) configured. After restart, DHCP finds the same addresses and no new ACD should be performed. This shows
+that the ACD state depends all the IP addresses on an interface,
+and thus it's done by NML3Cfg. The API for this is very simple. Users enable/disable ACD during nm_l3cfg_add_config()
+and receive events like [NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L303).
+Another advantage is that ACD now works for any kinds of addresses. Currently it only works for addresses
+from DHCP and link local addresses.
+
+NML3Cfg does not implement or drive DHCP. However, as it already does ACD it gained it's own IPv4LL
+"library": [NML3IPv4LL](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L3624).
+This will replace nettools' n-ipv4ll library, because that library also does ACD internally, while we want
+to use the holistic view that NML3Cfg has. What this means, is that the user (NMDevice)
+can request a NML3IPv4LL handle from the NML3Cfg instance, and it just does it with a simple API.
+All the user might do is to enable/disable the handle and to react to signals (if it cares to find
+out whether IPv4LL fails).
+
+The general parts of NML3Cfg are already implemented. It has unit tests and can be tested independently.
+You might note that NML3Cfg is not trivial already, but the API that it provides is as simple as possible:
+create immutable NML3ConfigData instance, and add/remove them. Optionally, handle the ACD events and
+listen to some events. The complexity that NML3Cfg has, will lead in the same amount simplify NMDevice.
+
+What is missing is NMDevice using this new API. Instead of creating and tracking NMIP4Config instances,
+it needs to track NML3ConfigData instances. In principle that sounds simple, in practice that changes
+large part of "nm-device.c".
+
+Thereby also the state machine for NM_DEVICE_STATE will be improved. It's anyway a rewrite. This will lay the
+groundwork for more flexible configuration of IP methods, with different failure modes (opportunistic or
+mandatory).
+
+What then also should be easier, to combine IPv4LL with other addressing methods. In Windows AFAIK, if you
+don't get a DHCP address it will configure a IPv4LL address. That is also what RFC suggests, but which we
+currently don't support.
+
+In general, change the way how external IP addresses/routes are tracked. This merge, intersect, subtract
+approach does not perform well. Currently we react on signals and it's hard to understand what happens
+in response to that, or whether it's really the correct thing to do. See yourself starting from
+[here](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L14214).
+
+### DHCP
+
+Currently, when NMDhcpClient receives a lease, it emits a signal with two things: the NMIP4Config
+instance (containing addresses, routes, DNS settings and other information for later use), and a string
+dictionary with the DHCP lease options (they are mainly used to expose them on D-Bus). The latter is
+immutable (meaning, it's not changed afterwards). That does not significantly change with L3Cfg. The
+difference is that instead of NMIP4Config a NML3ConfigData instance gets created. That instance then
+references the (immutable) strdict. With that, any part of the code that has access to the NML3ConfigData,
+also has access to the lease options. So instead of two separate
+pieces of information, the result of a lease event will only be a NML3ConfigData instance (which internally
+tracks the strdict with the DHCP lease options).
+
+Later, when NML3Cfg configures an interface, it takes all NML3ConfigData instances that were added to
+it, and merges them. [Currently](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3-config-data.c#L2693),
+the merged data will not contain the lease information, but it's probably not needed anyway.
+
+If it would be needed, the question is what happens if multiple lease informations are present
+during the merge. Duplicate leases would not commonly happen, but in general, the merging algorithm
+needs to take into account priorities and conflicting data.
+That is done by users who call [add](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L2658)
+to provide a priority for the NML3ConfigData instance.
+Later, the instances get sorted by priority and merging is smart to take that into account
+([here](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L2983)).
+
+Also, we currently inject the route-metric and table into the generated NMIP4Config.
+Those settings come from the connection profiles and not from DHCP. We will avoid that
+by allowing the routes in NML3ConfigData to be marked as metric\_any and table\_any.
+That way,the NML3ConfigData is independent (and immutable) with respect to those settings.
+The same happens for example with PPP, where the modem starts PPP, and currently the
+route and metric needs to be passed several layers down. But worst, those settings
+can change during reapply. Currently that means we need to hack NMIP4Config with
+those changes. Later, we will only tell NML3Cfg to track the NML3ConfigData with
+different settings.
+
+### DNS
+
+DNS information is currently set in the NMIP4Config instances. That happens for example with the DNS information
+from a DHCP lease, but also with the static DNS settings from the connection profile. Later, the same information
+will packed in NML3ConfigData.
+
+One nice difference is again the immutability. Currently, NMDnsManager keeps a reference to all relevant NMIP4Config instances,
+but as they are mutable, it needs to [subscribe](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/dns/nm-dns-manager.c#L275)
+to changes. Later, when a NML3ConfigData instance "changes", it means it was
+replaced by a different one and NMDnsManager needs to update its list of tracked NML3ConfigData. I find that
+cleaner, because adding and removal to the list of NMIP4Config/NML3ConfigData happens anyway and needs to be handled.
+
+
+Related Bugs
+------------
+
+* Main bug:
+
+ - [rh#1868254](https://bugzilla.redhat.com/show_bug.cgi?id=1868254):
+ "refactor NetworkManager's IP configuration done by NMDevice"
+
+* Follow up but to improve model of devices:
+
+ - [rh#1066703](https://bugzilla.redhat.com/show_bug.cgi?id=1066703):
+ "\[RFE\] Handle parent/child relationships more cleanly"
+
+* Flexible IP methods:
+
+ - [rh#1791624](https://bugzilla.redhat.com/show_bug.cgi?id=1791624):
+ "NetworkManager must not remove used bridge"
+
+* Improving performance issues, this will lay ground work:
+
+ - [rh#1847125](https://bugzilla.redhat.com/show_bug.cgi?id=1847125):
+ "\[RFE\] Improve 20% performance on creating 1000 bridge over 1000 VLANs"
+
+ - [rh#1861527](https://bugzilla.redhat.com/show_bug.cgi?id=1861527):
+ "Excessive memory and CPU usage on a router with IPv6 BGP feed"
+
+ - [rh#1753677](https://bugzilla.redhat.com/show_bug.cgi?id=1753677):
+ "High cpu usage while non-controlled interface is mangling tc filters"
+
diff --git a/src/core/README.next.ip-config.md b/src/core/README.next.ip-config.md
new file mode 100644
index 0000000000..e5be74f133
--- /dev/null
+++ b/src/core/README.next.ip-config.md
@@ -0,0 +1,59 @@
+Rework `NMIP[46]Config` for `next` branch
+=========================================
+
+The `next` branch is a large rework of internals, how IP configuration is done by `NMDevice`.
+
+Previously, there are two `GObject`s named `NMIP4Config` and `NMIP6Config`. These
+serve different purposes:
+
+1) They are data containers that can track IP configuration. As such, `NMDevice`
+ and various parts (like `NMDhcpClient`) create them, pass them around and
+ mutate/merge them to track the IP configuration.
+
+2) They are also subclasses of `NMDBusObject` and exported on D-Bus as
+ `/org/freedesktop/NetworkManager/IP4Config/1`, etc. As such, see their
+ [D-Bus API](../../introspection/org.freedesktop.NetworkManager.IP4Config.xml)
+ (and [for IPv6](../../introspection/org.freedesktop.NetworkManager.IP6Config.xml)).
+
+`next` branch will replace use 1) with `NML3ConfigData`. `NML3ConfigData` are immutable
+(sealable) data containers with little logic. This leaves `NMIP4Config` to only
+implement 2).
+
+This needs to be reworked.
+
+* Now `NMIP4Config` and `NMIP6Config` are subclasses of `NMIPConfig`. The goal
+ is to treat IPv4/IPv6 similar and generically. Probably there should be very
+ little code in the subclasses left and most should move to the parent classes.
+ We still need separate GObject types though, because that is how `NMDBusObject`'s
+ glue code can handle different D-Bus paths.
+
+* Now `NML3Cfg` is a handle for the IP configuration parameters of a device (ifindex).
+ As `NMIPConfig` mostly is about exporting the current IP configuration, it probably
+ can get most of it from there (and by listening to signals to that).
+
+* Note that `NMDevice`, `NMActiveConnection` refer `NMIP[46]Config`s, and most
+ importantly, the respective D-Bus objects refer to them. As `NMVpnConnection`
+ (and "org.freedesktop.NetworkManager.VPN.Connection" interface) are modeled
+ as "subclasses" of `NMActiveConnection`, they also have one. That means,
+ it's not entirely clear what these properties even are. For example, currently,
+ `NMDevice` does a (terrible) dance of tracking external `NMIP[46]Config` objects,
+ merging, intersecting and subtracting them with other `NMIP4Config` objects
+ to get the merged one, which is then exported on D-Bus. That merged object
+ does therefore not directly expose the IP addresses that are actually
+ configured on the interface (`ip addr`), but more what NetworkManager
+ wanted to configure and the (terrible) feedback loop where the platform
+ addresses get synced. With `next` branch and `NML3Cfg` there is a clear distinction
+ between what NetworkManager wants to configure vs. what is actually configured.
+ I think for `NMDevice` and `NMActiveConnection`, the IP addresses on
+ "org.freedesktop.NetworkManager.IP4Config" should expose the IP addresses
+ that are actually in platform (`ip addr`). If there is a need to expose
+ additional information (like things that NetworkManager wanted to configure),
+ then this should be different/new API.
+ On the other hand, currently `NMVpnConnection`'s `NMIP4Config` only tracks the
+ IP addresses that come from the VPN plugin. So it's much more what it wants
+ to configure (from the VPN plugin), and not at all about what is configured
+ on the interface.
+ I think that needs to change. A `NMIPConfig` object on D-Bus exposes IP configuration
+ information about an netdev interface. Period. That also means that a `NMVpnConnection`
+ (which currently is like a active connection associated with the device) links to
+ the same `NMIPConfig` object as the underlying device.
diff --git a/src/core/devices/adsl/nm-device-adsl.c b/src/core/devices/adsl/nm-device-adsl.c
index adcf878523..0f1bf80363 100644
--- a/src/core/devices/adsl/nm-device-adsl.c
+++ b/src/core/devices/adsl/nm-device-adsl.c
@@ -15,13 +15,13 @@
#include <unistd.h>
#include <stdlib.h>
-#include "nm-ip4-config.h"
#include "devices/nm-device-private.h"
#include "libnm-platform/nm-platform.h"
-#include "ppp/nm-ppp-manager-call.h"
-#include "ppp/nm-ppp-status.h"
+#include "nm-manager.h"
#include "nm-setting-adsl.h"
#include "nm-utils.h"
+#include "ppp/nm-ppp-manager-call.h"
+#include "ppp/nm-ppp-status.h"
#define _NMLOG_DEVICE_TYPE NMDeviceAdsl
#include "devices/nm-device-logging.h"
@@ -34,15 +34,18 @@ typedef struct {
guint carrier_poll_id;
int atm_index;
- /* PPP */
NMPPPManager *ppp_manager;
+ const NML3ConfigData *l3cd_4;
+
/* RFC 2684 bridging (PPPoE over ATM) */
- int brfd;
- int nas_ifindex;
- char *nas_ifname;
- guint nas_update_id;
- guint nas_update_count;
+ int brfd;
+ int nas_ifindex;
+ char * nas_ifname;
+ GSource *nas_update_source;
+ guint nas_update_count;
+
+ bool stage2_ready_ppp : 1;
} NMDeviceAdslPrivate;
struct _NMDeviceAdsl {
@@ -271,7 +274,7 @@ pppoe_vcc_config(NMDeviceAdsl *self)
}
static gboolean
-nas_update_cb(gpointer user_data)
+nas_update_timeout_cb(gpointer user_data)
{
NMDeviceAdsl * self = NM_DEVICE_ADSL(user_data);
NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
@@ -284,33 +287,35 @@ nas_update_cb(gpointer user_data)
nm_assert(priv->nas_ifindex <= 0);
priv->nas_ifindex =
nm_platform_link_get_ifindex(nm_device_get_platform(device), priv->nas_ifname);
+
+ if (priv->nas_ifindex <= 0 && priv->nas_update_count <= 10) {
+ /* Keep waiting for it to appear */
+ return G_SOURCE_CONTINUE;
+ }
+
+ nm_clear_g_source_inst(&priv->nas_update_source);
+
if (priv->nas_ifindex <= 0) {
- if (priv->nas_update_count <= 10) {
- /* Keep waiting for it to appear */
- return G_SOURCE_CONTINUE;
- }
- priv->nas_update_id = 0;
_LOGW(LOGD_ADSL,
"failed to find br2684 interface %s ifindex after timeout",
priv->nas_ifname);
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_BR2684_FAILED);
- return G_SOURCE_REMOVE;
+ return G_SOURCE_CONTINUE;
}
- priv->nas_update_id = 0;
_LOGD(LOGD_ADSL, "using br2684 iface '%s' index %d", priv->nas_ifname, priv->nas_ifindex);
if (!pppoe_vcc_config(self)) {
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_BR2684_FAILED);
- return G_SOURCE_REMOVE;
+ return G_SOURCE_CONTINUE;
}
nm_device_activate_schedule_stage2_device_config(device, TRUE);
- return G_SOURCE_REMOVE;
+ return G_SOURCE_CONTINUE;
}
static gboolean
@@ -319,11 +324,11 @@ br2684_create_iface(NMDeviceAdsl *self)
NMDeviceAdslPrivate * priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
struct atm_newif_br2684 ni;
nm_auto_close int fd = -1;
- int err, errsv;
+ int err;
+ int errsv;
guint num = 0;
- if (nm_clear_g_source(&priv->nas_update_id))
- nm_assert_not_reached();
+ nm_assert(!priv->nas_update_source);
fd = socket(PF_ATMPVC, SOCK_DGRAM | SOCK_CLOEXEC, ATM_AAL5);
if (fd < 0) {
@@ -358,49 +363,19 @@ br2684_create_iface(NMDeviceAdsl *self)
nm_strdup_reset(&priv->nas_ifname, ni.ifname);
_LOGD(LOGD_ADSL, "waiting for br2684 iface '%s' to appear", priv->nas_ifname);
- priv->nas_update_count = 0;
- priv->nas_update_id = g_timeout_add(100, nas_update_cb, self);
+ priv->nas_update_count = 0;
+ priv->nas_update_source = nm_g_timeout_add_source(100, nas_update_timeout_cb, self);
return TRUE;
}
}
-static NMActStageReturn
-act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
-{
- NMDeviceAdsl * self = NM_DEVICE_ADSL(device);
- NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
- NMSettingAdsl * s_adsl;
- const char * protocol;
-
- s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
-
- g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE);
-
- protocol = nm_setting_adsl_get_protocol(s_adsl);
- _LOGD(LOGD_ADSL, "using ADSL protocol '%s'", protocol);
-
- if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) {
- /* PPPoA doesn't need anything special */
- return NM_ACT_STAGE_RETURN_SUCCESS;
- }
-
- if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
- /* PPPoE needs RFC2684 bridging before we can do PPP over it */
- if (priv->nas_ifindex <= 0) {
- if (priv->nas_update_id == 0) {
- if (!br2684_create_iface(self)) {
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
- }
- return NM_ACT_STAGE_RETURN_POSTPONE;
- }
- return NM_ACT_STAGE_RETURN_SUCCESS;
- }
+/*****************************************************************************/
- _LOGW(LOGD_ADSL, "unhandled ADSL protocol '%s'", protocol);
- return NM_ACT_STAGE_RETURN_SUCCESS;
-}
+/* FIXME(l3cfg:ppp): the way we drive NMPPPManager is more complicated than it
+ * should be. You can see that because NMDevicePPP and NMDeviceAdsl have this
+ * code idential. Also, NMDeviceEthernet does something sufficiently similar
+ * (for handling PPPoE). The API of NMPPPManager should be simplified and handle
+ * more of the complexity. */
static void
ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
@@ -422,110 +397,202 @@ ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_d
}
static void
-ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
+ppp_stage3_ready(NMDevice *device)
{
- NMDevice *device = NM_DEVICE(user_data);
+ NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(device);
+
+ nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_READY, priv->l3cd_4);
+}
- if (!nm_device_set_ip_ifindex(device, ifindex)) {
+static void
+ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
+{
+ NMDeviceAdsl * self = NM_DEVICE_ADSL(user_data);
+ NMDevice * device = NM_DEVICE(self);
+ NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
+ gs_free char * old_name = NULL;
+ gs_free_error GError *error = NULL;
+
+ if (!nm_device_take_over_link(device, ifindex, &old_name, &error)) {
+ _LOGW(LOGD_DEVICE | LOGD_PPP,
+ "could not take control of link %d: %s",
+ ifindex,
+ error->message);
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ return;
}
+
+ if (old_name)
+ nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP);
+
+ priv->stage2_ready_ppp = TRUE;
+ nm_device_activate_schedule_stage2_device_config(device, FALSE);
}
static void
-ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
+ppp_new_config(NMPPPManager * ppp_manager,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid,
+ gpointer user_data)
{
- NMDevice *device = NM_DEVICE(user_data);
+ NMDeviceAdsl * self = NM_DEVICE_ADSL(user_data);
+ NMDevice * device = NM_DEVICE(self);
+ NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
+
+ if (addr_family != AF_INET)
+ return;
+
+ _LOGT(LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd");
+
+ nm_l3_config_data_reset(&priv->l3cd_4, l3cd);
- /* Ignore PPP IP4 events that come in after initial configuration */
- if (nm_device_activate_ip4_state_in_conf(device))
- nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config));
+ if (nm_device_devip_get_state(device, AF_INET) == NM_DEVICE_IP_STATE_PENDING)
+ ppp_stage3_ready(device);
}
-static NMActStageReturn
-act_stage3_ip4_config_start(NMDevice * device,
- NMIP4Config ** out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+ppp_manager_clear(NMDeviceAdsl *self)
{
- NMDeviceAdsl * self = NM_DEVICE_ADSL(device);
NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
- NMSettingAdsl * s_adsl;
- NMActRequest * req;
- GError * err = NULL;
- const char * ppp_iface;
- req = nm_device_get_act_request(device);
+ priv->stage2_ready_ppp = FALSE;
- g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
+ if (priv->ppp_manager) {
+ g_signal_handlers_disconnect_by_func(priv->ppp_manager,
+ G_CALLBACK(ppp_state_changed),
+ self);
+ g_signal_handlers_disconnect_by_func(priv->ppp_manager, G_CALLBACK(ppp_ifindex_set), self);
+ g_signal_handlers_disconnect_by_func(priv->ppp_manager, G_CALLBACK(ppp_new_config), self);
- s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
+ nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL);
+ g_clear_object(&priv->ppp_manager);
+ }
- g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE);
+ nm_clear_l3cd(&priv->l3cd_4);
+}
- /* PPPoE uses the NAS interface, not the ATM interface */
- if (nm_streq0(nm_setting_adsl_get_protocol(s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
- nm_assert(priv->nas_ifname);
- ppp_iface = priv->nas_ifname;
+/*****************************************************************************/
- _LOGD(LOGD_ADSL, "starting PPPoE on br2684 interface %s", priv->nas_ifname);
- } else {
- ppp_iface = nm_device_get_iface(device);
- _LOGD(LOGD_ADSL, "starting PPPoA");
- }
+static NMActStageReturn
+act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
+{
+ NMDeviceAdsl * self = NM_DEVICE_ADSL(device);
+ NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
+ gs_free_error GError *error = NULL;
+ NMSettingAdsl * s_adsl;
+ const char * protocol;
+ NMActRequest * req;
+ const char * ppp_iface;
+
+ if (!priv->stage2_ready_ppp) {
+ s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
+
+ g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE);
+
+ protocol = nm_setting_adsl_get_protocol(s_adsl);
+
+ _LOGD(LOGD_ADSL, "using ADSL protocol '%s'", protocol);
+
+ if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) {
+ /* PPPoA doesn't need anything special */
+ } else if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
+ /* PPPoE needs RFC2684 bridging before we can do PPP over it */
+ if (priv->nas_ifindex <= 0) {
+ if (!priv->nas_update_source) {
+ if (!br2684_create_iface(self)) {
+ NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED);
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+ }
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+ }
+ } else
+ nm_assert(nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM));
- priv->ppp_manager = nm_ppp_manager_create(ppp_iface, &err);
+ if (priv->ppp_manager)
+ return NM_ACT_STAGE_RETURN_POSTPONE;
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- nm_device_get_route_table(device, AF_INET),
- nm_device_get_route_metric(device, AF_INET),
- nm_device_get_route_table(device, AF_INET6),
- nm_device_get_route_metric(device, AF_INET6));
- }
+ req = nm_device_get_act_request(device);
+ g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
+
+ /* PPPoE uses the NAS interface, not the ATM interface */
+ if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
+ nm_assert(priv->nas_ifname);
+ ppp_iface = priv->nas_ifname;
+ _LOGD(LOGD_ADSL, "starting PPPoE on br2684 interface %s", priv->nas_ifname);
+ } else {
+ ppp_iface = nm_device_get_iface(device);
+ _LOGD(LOGD_ADSL, "starting PPPoA");
+ }
- if (!priv->ppp_manager
- || !nm_ppp_manager_start(priv->ppp_manager,
- req,
- nm_setting_adsl_get_username(s_adsl),
- 30,
- 0,
- &err)) {
- _LOGW(LOGD_ADSL, "PPP failed to start: %s", err->message);
- g_error_free(err);
+ priv->ppp_manager = nm_ppp_manager_create(ppp_iface, &error);
- g_clear_object(&priv->ppp_manager);
+ if (!priv->ppp_manager) {
+ _LOGW(LOGD_DEVICE, "PPPoE failed to create manager: %s", error->message);
+ *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+
+ g_signal_connect(priv->ppp_manager,
+ NM_PPP_MANAGER_SIGNAL_STATE_CHANGED,
+ G_CALLBACK(ppp_state_changed),
+ self);
+ g_signal_connect(priv->ppp_manager,
+ NM_PPP_MANAGER_SIGNAL_IFINDEX_SET,
+ G_CALLBACK(ppp_ifindex_set),
+ self);
+ g_signal_connect(priv->ppp_manager,
+ NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
+ G_CALLBACK(ppp_new_config),
+ self);
+
+ if (!nm_ppp_manager_start(priv->ppp_manager,
+ req,
+ nm_setting_adsl_get_username(s_adsl),
+ 30,
+ 0,
+ &error)) {
+ _LOGW(LOGD_ADSL, "PPP failed to start: %s", error->message);
+ ppp_manager_clear(self);
+ *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED);
- return NM_ACT_STAGE_RETURN_FAILURE;
+ return NM_ACT_STAGE_RETURN_POSTPONE;
}
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_STATE_CHANGED,
- G_CALLBACK(ppp_state_changed),
- self);
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IFINDEX_SET,
- G_CALLBACK(ppp_ifindex_set),
- self);
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_CALLBACK(ppp_ip4_config),
- self);
- return NM_ACT_STAGE_RETURN_POSTPONE;
+ return NM_ACT_STAGE_RETURN_SUCCESS;
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
{
- if (addr_family == AF_INET)
- return act_stage3_ip4_config_start(device, (NMIP4Config **) out_config, out_failure_reason);
+ NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(device);
+
+ if (!NM_IS_IPv4(addr_family)) {
+ /* TODO: IPv6 is not implemented/handled. */
+ return;
+ }
- return NM_DEVICE_CLASS(nm_device_adsl_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ switch (nm_device_devip_get_state(device, addr_family)) {
+ case NM_DEVICE_IP_STATE_NONE:
+ if (priv->l3cd_4) {
+ ppp_stage3_ready(device);
+ return;
+ }
+ nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL);
+ return;
+ case NM_DEVICE_IP_STATE_PENDING:
+ nm_assert(!priv->l3cd_4);
+ return;
+ case NM_DEVICE_IP_STATE_FAILED:
+ case NM_DEVICE_IP_STATE_READY:
+ return;
+ }
+ nm_assert_not_reached();
}
static void
@@ -533,23 +600,15 @@ adsl_cleanup(NMDeviceAdsl *self)
{
NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
- if (priv->ppp_manager) {
- g_signal_handlers_disconnect_by_func(priv->ppp_manager,
- G_CALLBACK(ppp_state_changed),
- self);
- g_signal_handlers_disconnect_by_func(priv->ppp_manager, G_CALLBACK(ppp_ip4_config), self);
- nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL);
- g_clear_object(&priv->ppp_manager);
- }
+ ppp_manager_clear(self);
g_signal_handlers_disconnect_by_func(nm_device_get_platform(NM_DEVICE(self)),
G_CALLBACK(link_changed_cb),
self);
- nm_close(priv->brfd);
- priv->brfd = -1;
+ nm_clear_fd(&priv->brfd);
- nm_clear_g_source(&priv->nas_update_id);
+ nm_clear_g_source_inst(&priv->nas_update_source);
/* FIXME: kernel has no way of explicitly deleting the 'nasX' interface yet,
* so it gets leaked. It does get destroyed when it's no longer in use,
@@ -699,9 +758,9 @@ nm_device_adsl_class_init(NMDeviceAdslClass *klass)
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
- device_class->act_stage2_config = act_stage2_config;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
- device_class->deactivate = deactivate;
+ device_class->act_stage2_config = act_stage2_config;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
+ device_class->deactivate = deactivate;
obj_properties[PROP_ATM_INDEX] =
g_param_spec_int(NM_DEVICE_ADSL_ATM_INDEX,
diff --git a/src/core/devices/bluetooth/nm-device-bt.c b/src/core/devices/bluetooth/nm-device-bt.c
index 3dbfbbe06e..6d5923cee9 100644
--- a/src/core/devices/bluetooth/nm-device-bt.c
+++ b/src/core/devices/bluetooth/nm-device-bt.c
@@ -26,7 +26,6 @@
#include "settings/nm-settings-connection.h"
#include "nm-utils.h"
#include "nm-bt-error.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "devices/wwan/nm-modem-manager.h"
@@ -438,26 +437,28 @@ ppp_failed(NMModem *modem, guint i_reason, gpointer user_data)
case NM_DEVICE_STATE_IP_CHECK:
case NM_DEVICE_STATE_SECONDARIES:
case NM_DEVICE_STATE_ACTIVATED:
- if (nm_device_activate_ip4_state_in_conf(device))
- nm_device_activate_schedule_ip_config_timeout(device, AF_INET);
- else if (nm_device_activate_ip6_state_in_conf(device))
- nm_device_activate_schedule_ip_config_timeout(device, AF_INET6);
- else if (nm_device_activate_ip4_state_done(device)) {
- nm_device_ip_method_failed(device,
- AF_INET,
- NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- } else if (nm_device_activate_ip6_state_done(device)) {
- nm_device_ip_method_failed(device,
- AF_INET6,
- NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- } else {
- _LOGW(LOGD_MB,
- "PPP failure in unexpected state %u",
- (guint) nm_device_get_state(device));
- nm_device_state_changed(device,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- }
+ /* FIXME(l3cfg) */
+ (void) self;
+ //if (nm_device_activate_get_ip_state(device, AF_INET) == NM_DEVICE_IP_STATE_PENDING)
+ // nm_device_activate_schedule_ip_config_timeout(device, AF_INET);
+ //else if (nm_device_activate_get_ip_state(device, AF_INET6) == NM_DEVICE_IP_STATE_PENDING)
+ // nm_device_activate_schedule_ip_config_timeout(device, AF_INET6);
+ //else if (nm_device_activate_get_ip_state(device, AF_INET) == NM_DEVICE_IP_STATE_READY) {
+ // nm_device_dev_ip_method_failed(device,
+ // AF_INET,
+ // NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ //} else if (nm_device_activate_get_ip_state(device, AF_INET6) == NM_DEVICE_IP_STATE_READY) {
+ // nm_device_dev_ip_method_failed(device,
+ // AF_INET6,
+ // NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ //} else {
+ // _LOGW(LOGD_MB,
+ // "PPP failure in unexpected state %u",
+ // (guint) nm_device_get_state(device));
+ // nm_device_state_changed(device,
+ // NM_DEVICE_STATE_FAILED,
+ // NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ //}
break;
default:
break;
@@ -547,22 +548,39 @@ device_state_changed(NMDevice * device,
}
static void
-modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpointer user_data)
+modem_new_config(NMModem * modem,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ gboolean do_slaac,
+ const NMUtilsIPv6IfaceId *iid,
+ GError * error,
+ gpointer user_data)
{
+#if 0
NMDeviceBt *self = NM_DEVICE_BT(user_data);
NMDevice * device = NM_DEVICE(self);
- g_return_if_fail(nm_device_activate_ip4_state_in_conf(device) == TRUE);
+ if (addr_family != AF_INET)
+ return;
+
+ /* FIXME(l3cfg): this is not right to handle IP states. */
+ g_return_if_fail(nm_device_activate_get_ip_state(device, AF_INET)
+ == NM_DEVICE_IP_STATE_PENDING);
if (error) {
_LOGW(LOGD_MB | LOGD_IP4 | LOGD_BT,
"retrieving IP4 configuration failed: %s",
error->message);
- nm_device_ip_method_failed(device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ nm_device_dev_ip_method_failed(device,
+ AF_INET,
+ NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
return;
}
- nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config));
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET);
+#endif
+ //XXX
}
static void
@@ -687,7 +705,7 @@ modem_try_claim(NMDeviceBt *self, NMModem *modem)
g_signal_connect(modem, NM_MODEM_PPP_STATS, G_CALLBACK(ppp_stats), self);
g_signal_connect(modem, NM_MODEM_PPP_FAILED, G_CALLBACK(ppp_failed), self);
g_signal_connect(modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK(modem_prepare_result), self);
- g_signal_connect(modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK(modem_ip4_config_result), self);
+ g_signal_connect(modem, NM_MODEM_NEW_CONFIG, G_CALLBACK(modem_new_config), self);
g_signal_connect(modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK(modem_auth_requested), self);
g_signal_connect(modem, NM_MODEM_AUTH_RESULT, G_CALLBACK(modem_auth_result), self);
g_signal_connect(modem, NM_MODEM_STATE_CHANGED, G_CALLBACK(modem_state_cb), self);
@@ -998,29 +1016,23 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
return NM_ACT_STAGE_RETURN_SUCCESS;
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
{
- NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device);
- gboolean autoip4 = FALSE;
- NMActStageReturn ret;
+ NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device);
if (priv->connect_bt_type != NM_BT_CAPABILITY_DUN)
- goto out_chain_up;
+ return;
+ XXX("FIXME(l3cfg)");
+#if 0
if (!NM_IS_IPv4(addr_family))
return nm_modem_stage3_ip6_config_start(priv->modem, device, out_failure_reason);
ret = nm_modem_stage3_ip4_config_start(priv->modem, device, &autoip4, out_failure_reason);
if (ret != NM_ACT_STAGE_RETURN_SUCCESS || !autoip4)
return ret;
-
-out_chain_up:
- return NM_DEVICE_CLASS(nm_device_bt_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+#endif
}
static void
@@ -1344,7 +1356,7 @@ nm_device_bt_class_init(NMDeviceBtClass *klass)
device_class->deactivate = deactivate;
device_class->act_stage1_prepare = act_stage1_prepare;
device_class->act_stage2_config = act_stage2_config;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
device_class->check_connection_compatible = check_connection_compatible;
device_class->check_connection_available = check_connection_available;
device_class->complete_connection = complete_connection;
diff --git a/src/core/devices/nm-acd-manager.c b/src/core/devices/nm-acd-manager.c
deleted file mode 100644
index c041163ef8..0000000000
--- a/src/core/devices/nm-acd-manager.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 - 2018 Red Hat, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "nm-acd-manager.h"
-
-#include <netinet/in.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <linux/if_ether.h>
-
-#include "libnm-platform/nm-platform.h"
-#include "nm-utils.h"
-#include "NetworkManagerUtils.h"
-#include "n-acd/src/n-acd.h"
-
-/*****************************************************************************/
-
-typedef enum {
- STATE_INIT,
- STATE_PROBING,
- STATE_PROBE_DONE,
- STATE_ANNOUNCING,
-} State;
-
-typedef struct {
- in_addr_t address;
- gboolean duplicate;
- NAcdProbe *probe;
-} AddressInfo;
-
-struct _NMAcdManager {
- int ifindex;
- guint8 hwaddr[ETH_ALEN];
- State state;
- GHashTable *addresses;
- guint completed;
- NAcd * acd;
- GSource * event_source;
-
- NMAcdCallbacks callbacks;
- gpointer user_data;
-};
-
-/*****************************************************************************/
-
-#define _NMLOG_DOMAIN LOGD_IP4
-#define _NMLOG_PREFIX_NAME "acd"
-#define _NMLOG(level, ...) \
- G_STMT_START \
- { \
- char _sbuf[64]; \
- \
- nm_log((level), \
- _NMLOG_DOMAIN, \
- self && self->ifindex > 0 \
- ? nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex) \
- : NULL, \
- NULL, \
- "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
- _NMLOG_PREFIX_NAME, \
- self ? nm_sprintf_buf(_sbuf, "[%p,%d]", self, self->ifindex) \
- : "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
- } \
- G_STMT_END
-
-/*****************************************************************************/
-
-static const char *
-_acd_event_to_string(unsigned int event)
-{
- switch (event) {
- case N_ACD_EVENT_READY:
- return "ready";
- case N_ACD_EVENT_USED:
- return "used";
- case N_ACD_EVENT_DEFENDED:
- return "defended";
- case N_ACD_EVENT_CONFLICT:
- return "conflict";
- case N_ACD_EVENT_DOWN:
- return "down";
- }
- return NULL;
-}
-
-#define ACD_EVENT_TO_STRING_BUF_SIZE 50
-
-static const char *
-_acd_event_to_string_buf(unsigned event, char buffer[static ACD_EVENT_TO_STRING_BUF_SIZE])
-{
- const char *s;
-
- s = _acd_event_to_string(event);
- if (s)
- return s;
-
- g_snprintf(buffer, ACD_EVENT_TO_STRING_BUF_SIZE, "(%u)", event);
- return buffer;
-}
-
-static const char *
-acd_error_to_string(int error)
-{
- if (error < 0)
- return nm_strerror_native(-error);
-
- switch (error) {
- case _N_ACD_E_SUCCESS:
- return "success";
- case N_ACD_E_PREEMPTED:
- return "preempted";
- case N_ACD_E_INVALID_ARGUMENT:
- return "invalid argument";
- }
-
- g_return_val_if_reached(NULL);
-}
-
-static int
-acd_error_to_nmerr(int error, gboolean always_fail)
-{
- if (error < 0)
- return -nm_errno_native(error);
-
- if (always_fail) {
- if (NM_IN_SET(error, N_ACD_E_PREEMPTED, N_ACD_E_INVALID_ARGUMENT))
- return -NME_UNSPEC;
- g_return_val_if_reached(-NME_UNSPEC);
- }
-
- /* so, @error is either zero (indicating success) or one
- * of the special status codes like N_ACD_E_*. In both cases,
- * return the positive value here. */
- if (NM_IN_SET(error, _N_ACD_E_SUCCESS, N_ACD_E_PREEMPTED, N_ACD_E_INVALID_ARGUMENT))
- return error;
-
- g_return_val_if_reached(error);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_acd_manager_add_address:
- * @self: a #NMAcdManager
- * @address: an IP address
- *
- * Add @address to the list of IP addresses to probe.
-
- * Returns: %TRUE on success, %FALSE if the address was already in the list
- */
-gboolean
-nm_acd_manager_add_address(NMAcdManager *self, in_addr_t address)
-{
- AddressInfo *info;
-
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(self->state == STATE_INIT, FALSE);
-
- if (g_hash_table_lookup(self->addresses, GUINT_TO_POINTER(address)))
- return FALSE;
-
- info = g_slice_new0(AddressInfo);
- info->address = address;
-
- g_hash_table_insert(self->addresses, GUINT_TO_POINTER(address), info);
-
- return TRUE;
-}
-
-static gboolean
-acd_event(int fd, GIOCondition condition, gpointer data)
-{
- NMAcdManager *self = data;
- NAcdEvent * event;
- AddressInfo * info;
- gboolean emit_probe_terminated = FALSE;
- char address_str[INET_ADDRSTRLEN];
- int r;
-
- if (n_acd_dispatch(self->acd))
- return G_SOURCE_CONTINUE;
-
- while (!n_acd_pop_event(self->acd, &event) && event) {
- char to_string_buffer[ACD_EVENT_TO_STRING_BUF_SIZE];
- gs_free char *hwaddr_str = NULL;
- gboolean check_probing_done = FALSE;
- char buf[ETH_ALEN * 3];
-
- switch (event->event) {
- case N_ACD_EVENT_READY:
- n_acd_probe_get_userdata(event->ready.probe, (void **) &info);
- info->duplicate = FALSE;
- if (self->state == STATE_ANNOUNCING) {
- /* fake probe ended, start announcing */
- r = n_acd_probe_announce(info->probe, N_ACD_DEFEND_ONCE);
- if (r) {
- _LOGW("couldn't announce address %s on interface '%s': %s",
- _nm_utils_inet4_ntop(info->address, address_str),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- } else {
- _LOGD("announcing address %s (hw-addr %s)",
- _nm_utils_inet4_ntop(info->address, address_str),
- _nm_utils_hwaddr_ntoa(self->hwaddr, ETH_ALEN, TRUE, buf, sizeof(buf)));
- }
- }
- check_probing_done = TRUE;
- break;
- case N_ACD_EVENT_USED:
- n_acd_probe_get_userdata(event->used.probe, (void **) &info);
- info->duplicate = TRUE;
- check_probing_done = TRUE;
- break;
- case N_ACD_EVENT_DEFENDED:
- n_acd_probe_get_userdata(event->defended.probe, (void **) &info);
- _LOGD("defended address %s from host %s",
- _nm_utils_inet4_ntop(info->address, address_str),
- (hwaddr_str =
- nm_utils_hwaddr_ntoa(event->defended.sender, event->defended.n_sender)));
- break;
- case N_ACD_EVENT_CONFLICT:
- n_acd_probe_get_userdata(event->conflict.probe, (void **) &info);
- _LOGW("conflict for address %s detected with host %s on interface '%s'",
- _nm_utils_inet4_ntop(info->address, address_str),
- (hwaddr_str =
- nm_utils_hwaddr_ntoa(event->defended.sender, event->defended.n_sender)),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex));
- break;
- default:
- _LOGD("unhandled event '%s'", _acd_event_to_string_buf(event->event, to_string_buffer));
- break;
- }
-
- if (check_probing_done && self->state == STATE_PROBING
- && ++self->completed == g_hash_table_size(self->addresses)) {
- self->state = STATE_PROBE_DONE;
- emit_probe_terminated = TRUE;
- }
- }
-
- if (emit_probe_terminated) {
- if (self->callbacks.probe_terminated_callback) {
- self->callbacks.probe_terminated_callback(self, self->user_data);
- }
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-static gboolean
-acd_probe_add(NMAcdManager *self, AddressInfo *info, guint64 timeout)
-{
- NAcdProbeConfig *probe_config;
- int r;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- r = n_acd_probe_config_new(&probe_config);
- if (r) {
- _LOGW("could not create probe config for %s on interface '%s': %s",
- _nm_utils_inet4_ntop(info->address, sbuf),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- return FALSE;
- }
-
- n_acd_probe_config_set_ip(probe_config, (struct in_addr){info->address});
- n_acd_probe_config_set_timeout(probe_config, timeout);
-
- r = n_acd_probe(self->acd, &info->probe, probe_config);
- if (r) {
- _LOGW("could not start probe for %s on interface '%s': %s",
- _nm_utils_inet4_ntop(info->address, sbuf),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- n_acd_probe_config_free(probe_config);
- return FALSE;
- }
-
- n_acd_probe_set_userdata(info->probe, info);
- n_acd_probe_config_free(probe_config);
-
- return TRUE;
-}
-
-static int
-acd_init(NMAcdManager *self)
-{
- NAcdConfig *config;
- int r;
-
- if (self->acd)
- return 0;
-
- r = n_acd_config_new(&config);
- if (r)
- return r;
-
- n_acd_config_set_ifindex(config, self->ifindex);
- n_acd_config_set_transport(config, N_ACD_TRANSPORT_ETHERNET);
- n_acd_config_set_mac(config, self->hwaddr, ETH_ALEN);
-
- r = n_acd_new(&self->acd, config);
- n_acd_config_free(config);
- return r;
-}
-
-/**
- * nm_acd_manager_start_probe:
- * @self: a #NMAcdManager
- * @timeout: maximum probe duration in milliseconds
- * @error: location to store error, or %NULL
- *
- * Start probing IP addresses for duplicates; when the probe terminates a
- * PROBE_TERMINATED signal is emitted.
- *
- * Returns: 0 on success or a negative NetworkManager error code (NME_*).
- */
-int
-nm_acd_manager_start_probe(NMAcdManager *self, guint timeout)
-{
- GHashTableIter iter;
- AddressInfo * info;
- gboolean success = FALSE;
- int fd, r;
-
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(self->state == STATE_INIT, FALSE);
-
- r = acd_init(self);
- if (r) {
- _LOGW("couldn't init ACD for probing on interface '%s': %s",
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- return acd_error_to_nmerr(r, TRUE);
- }
-
- self->completed = 0;
-
- g_hash_table_iter_init(&iter, self->addresses);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &info))
- success |= acd_probe_add(self, info, timeout);
-
- if (success)
- self->state = STATE_PROBING;
-
- nm_assert(!self->event_source);
- n_acd_get_fd(self->acd, &fd);
- self->event_source = nm_g_unix_fd_add_source(fd, G_IO_IN, acd_event, self);
-
- return success ? 0 : -NME_UNSPEC;
-}
-
-/**
- * nm_acd_manager_check_address:
- * @self: a #NMAcdManager
- * @address: an IP address
- *
- * Check if an IP address is duplicate. @address must have been added with
- * nm_acd_manager_add_address().
- *
- * Returns: %TRUE if the address is not duplicate, %FALSE otherwise
- */
-gboolean
-nm_acd_manager_check_address(NMAcdManager *self, in_addr_t address)
-{
- AddressInfo *info;
-
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(NM_IN_SET(self->state, STATE_INIT, STATE_PROBE_DONE), FALSE);
-
- info = g_hash_table_lookup(self->addresses, GUINT_TO_POINTER(address));
- g_return_val_if_fail(info, FALSE);
-
- return !info->duplicate;
-}
-
-/**
- * nm_acd_manager_announce_addresses:
- * @self: a #NMAcdManager
- *
- * Start announcing addresses.
- *
- * Returns: a negative NetworkManager error number or zero on success.
- */
-int
-nm_acd_manager_announce_addresses(NMAcdManager *self)
-{
- GHashTableIter iter;
- AddressInfo * info;
- int r;
- int fd;
- gboolean success = TRUE;
- char buf[ETH_ALEN * 3];
-
- r = acd_init(self);
- if (r) {
- _LOGW("couldn't init ACD for announcing addresses on interface '%s': %s",
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- return acd_error_to_nmerr(r, TRUE);
- }
-
- if (self->state == STATE_INIT) {
- /* n-acd can't announce without probing, therefore let's
- * start a fake probe with zero timeout and then perform
- * the announcement. */
- g_hash_table_iter_init(&iter, self->addresses);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &info)) {
- if (!acd_probe_add(self, info, 0))
- success = FALSE;
- }
- self->state = STATE_ANNOUNCING;
- } else if (self->state == STATE_ANNOUNCING) {
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- g_hash_table_iter_init(&iter, self->addresses);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &info)) {
- if (info->duplicate)
- continue;
- r = n_acd_probe_announce(info->probe, N_ACD_DEFEND_ONCE);
- if (r) {
- _LOGW("couldn't announce address %s on interface '%s': %s",
- _nm_utils_inet4_ntop(info->address, sbuf),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- success = FALSE;
- } else
- _LOGD("announcing address %s (hw-addr %s)",
- _nm_utils_inet4_ntop(info->address, sbuf),
- _nm_utils_hwaddr_ntoa(self->hwaddr, ETH_ALEN, TRUE, buf, sizeof(buf)));
- }
- }
-
- if (!self->event_source) {
- n_acd_get_fd(self->acd, &fd);
- self->event_source = nm_g_unix_fd_add_source(fd, G_IO_IN, acd_event, self);
- }
-
- return success ? 0 : -NME_UNSPEC;
-}
-
-static void
-destroy_address_info(gpointer data)
-{
- AddressInfo *info = (AddressInfo *) data;
-
- n_acd_probe_free(info->probe);
-
- g_slice_free(AddressInfo, info);
-}
-
-/*****************************************************************************/
-
-NMAcdManager *
-nm_acd_manager_new(int ifindex,
- const guint8 * hwaddr,
- guint hwaddr_len,
- const NMAcdCallbacks *callbacks,
- gpointer user_data)
-{
- NMAcdManager *self;
-
- g_return_val_if_fail(ifindex > 0, NULL);
- g_return_val_if_fail(hwaddr, NULL);
- g_return_val_if_fail(hwaddr_len == ETH_ALEN, NULL);
-
- self = g_slice_new0(NMAcdManager);
-
- if (callbacks)
- self->callbacks = *callbacks;
- self->user_data = user_data;
-
- self->addresses = g_hash_table_new_full(nm_direct_hash, NULL, NULL, destroy_address_info);
- self->state = STATE_INIT;
- self->ifindex = ifindex;
- memcpy(self->hwaddr, hwaddr, ETH_ALEN);
- return self;
-}
-
-void
-nm_acd_manager_free(NMAcdManager *self)
-{
- g_return_if_fail(self);
-
- if (self->callbacks.user_data_destroy)
- self->callbacks.user_data_destroy(self->user_data);
-
- nm_clear_pointer(&self->addresses, g_hash_table_destroy);
- nm_clear_g_source_inst(&self->event_source);
- nm_clear_pointer(&self->acd, n_acd_unref);
-
- g_slice_free(NMAcdManager, self);
-}
diff --git a/src/core/devices/nm-acd-manager.h b/src/core/devices/nm-acd-manager.h
deleted file mode 100644
index e8ef6f2b99..0000000000
--- a/src/core/devices/nm-acd-manager.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 - 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_ACD_MANAGER__
-#define __NM_ACD_MANAGER__
-
-#include <netinet/in.h>
-
-typedef struct _NMAcdManager NMAcdManager;
-
-typedef struct {
- void (*probe_terminated_callback)(NMAcdManager *self, gpointer user_data);
- GDestroyNotify user_data_destroy;
-} NMAcdCallbacks;
-
-NMAcdManager *nm_acd_manager_new(int ifindex,
- const guint8 * hwaddr,
- guint hwaddr_len,
- const NMAcdCallbacks *callbacks,
- gpointer user_data);
-
-void nm_acd_manager_free(NMAcdManager *self);
-
-gboolean nm_acd_manager_add_address(NMAcdManager *self, in_addr_t address);
-int nm_acd_manager_start_probe(NMAcdManager *self, guint timeout);
-gboolean nm_acd_manager_check_address(NMAcdManager *self, in_addr_t address);
-int nm_acd_manager_announce_addresses(NMAcdManager *self);
-
-NM_AUTO_DEFINE_FCN0(NMAcdManager *, _nm_auto_free_acdmgr, nm_acd_manager_free);
-#define nm_auto_free_acdmgr nm_auto(_nm_auto_free_acdmgr)
-
-#endif /* __NM_ACD_MANAGER__ */
diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c
index f7d78f57b7..3e7fd0ee18 100644
--- a/src/core/devices/nm-device-bond.c
+++ b/src/core/devices/nm-device-bond.c
@@ -16,7 +16,6 @@
#include "nm-device-factory.h"
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
#include "libnm-core-intern/nm-core-internal.h"
-#include "nm-ip4-config.h"
#include "nm-setting-bond-port.h"
#define _NMLOG_DEVICE_TYPE NMDeviceBond
diff --git a/src/core/devices/nm-device-dummy.c b/src/core/devices/nm-device-dummy.c
index 4c12648fc1..60ac524988 100644
--- a/src/core/devices/nm-device-dummy.c
+++ b/src/core/devices/nm-device-dummy.c
@@ -12,7 +12,6 @@
#include "nm-act-request.h"
#include "nm-device-private.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-dummy.h"
diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c
index 667ea9b927..f2073a3f51 100644
--- a/src/core/devices/nm-device-ethernet.c
+++ b/src/core/devices/nm-device-ethernet.c
@@ -14,38 +14,38 @@
#include <libudev.h>
#include <linux/if_ether.h>
-#include "libnm-glib-aux/nm-uuid.h"
-#include "nm-device-private.h"
-#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#include "NetworkManagerUtils.h"
-#include "supplicant/nm-supplicant-manager.h"
-#include "supplicant/nm-supplicant-interface.h"
-#include "supplicant/nm-supplicant-config.h"
-#include "ppp/nm-ppp-manager.h"
-#include "ppp/nm-ppp-manager-call.h"
-#include "ppp/nm-ppp-status.h"
-#include "libnm-platform/nm-platform.h"
+#include "NetworkManagerUtils.h"
+#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
+#include "libnm-core-intern/nm-core-internal.h"
+#include "libnm-glib-aux/nm-uuid.h"
#include "libnm-platform/nm-platform-utils.h"
-#include "nm-dcb.h"
-#include "settings/nm-settings-connection.h"
+#include "libnm-platform/nm-platform.h"
+#include "libnm-udev-aux/nm-udev-utils.h"
+#include "nm-act-request.h"
#include "nm-config.h"
+#include "nm-dcb.h"
#include "nm-device-ethernet-utils.h"
-#include "settings/nm-settings.h"
#include "nm-device-factory.h"
-#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
-#include "libnm-core-intern/nm-core-internal.h"
-#include "NetworkManagerUtils.h"
-#include "libnm-udev-aux/nm-udev-utils.h"
+#include "nm-device-private.h"
#include "nm-device-veth.h"
+#include "nm-manager.h"
+#include "ppp/nm-ppp-manager-call.h"
+#include "ppp/nm-ppp-manager.h"
+#include "ppp/nm-ppp-status.h"
+#include "settings/nm-settings-connection.h"
+#include "settings/nm-settings.h"
+#include "supplicant/nm-supplicant-config.h"
+#include "supplicant/nm-supplicant-interface.h"
+#include "supplicant/nm-supplicant-manager.h"
#define _NMLOG_DEVICE_TYPE NMDeviceEthernet
#include "nm-device-logging.h"
/*****************************************************************************/
-#define PPPOE_RECONNECT_DELAY 7
-#define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */
+#define PPPOE_RECONNECT_DELAY_MSEC 7000
+#define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */
#define SUPPLICANT_LNK_TIMEOUT_SEC 15
@@ -95,10 +95,12 @@ typedef struct _NMDeviceEthernetPrivate {
NMActRequestGetSecretsCallId *wired_secrets_id;
- /* PPPoE */
- NMPPPManager *ppp_manager;
- gint32 last_pppoe_time;
- guint pppoe_wait_id;
+ struct {
+ NMPPPManager * ppp_manager;
+ GSource * wait_source;
+ gint64 last_pppoe_time_msec;
+ const NML3ConfigData *l3cd_4;
+ } ppp_data;
/* DCB */
DcbWait dcb_wait;
@@ -113,6 +115,10 @@ typedef struct _NMDeviceEthernetPrivate {
bool ethtool_prev_set : 1;
bool ethtool_prev_autoneg : 1;
+ bool stage2_ready_dcb : 1;
+
+ bool stage2_ready_ppp : 1;
+
} NMDeviceEthernetPrivate;
NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceEthernet, PROP_SPEED, PROP_S390_SUBCHANNELS, );
@@ -468,27 +474,25 @@ wired_auth_cond_fail(NMDeviceEthernet *self, NMDeviceStateReason reason)
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
NMDevice * device = NM_DEVICE(self);
- if (wired_auth_is_optional(self)) {
- _LOGI(
- LOGD_DEVICE | LOGD_ETHER,
- "Activation: (ethernet) 802.1X authentication is optional, continuing after a failure");
- if (NM_IN_SET(nm_device_get_state(device),
- NM_DEVICE_STATE_CONFIG,
- NM_DEVICE_STATE_NEED_AUTH))
- nm_device_activate_schedule_stage3_ip_config_start(device);
-
- if (!priv->supplicant.auth_state_id) {
- priv->supplicant.auth_state_id =
- g_signal_connect(priv->supplicant.iface,
- "notify::" NM_SUPPLICANT_INTERFACE_AUTH_STATE,
- G_CALLBACK(supplicant_auth_state_changed),
- self);
- }
+ if (!wired_auth_is_optional(self)) {
+ supplicant_interface_release(self);
+ nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason);
return;
}
- supplicant_interface_release(self);
- nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason);
+ _LOGI(LOGD_DEVICE | LOGD_ETHER,
+ "Activation: (ethernet) 802.1X authentication is optional, continuing after a failure");
+
+ if (NM_IN_SET(nm_device_get_state(device), NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_NEED_AUTH))
+ nm_device_activate_schedule_stage2_device_config(device, FALSE);
+
+ if (!priv->supplicant.auth_state_id) {
+ priv->supplicant.auth_state_id =
+ g_signal_connect(priv->supplicant.iface,
+ "notify::" NM_SUPPLICANT_INTERFACE_AUTH_STATE,
+ G_CALLBACK(supplicant_auth_state_changed),
+ self);
+ }
}
static void
@@ -646,12 +650,12 @@ supplicant_iface_state_is_completed(NMDeviceEthernet *self, NMSupplicantInterfac
nm_clear_g_source(&priv->supplicant.con_timeout_id);
/* If this is the initial association during device activation,
- * schedule the next activation stage.
+ * schedule the activation stage again to proceed.
*/
if (nm_device_get_state(NM_DEVICE(self)) == NM_DEVICE_STATE_CONFIG) {
_LOGI(LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) Stage 2 of 5 (Device Configure) successful.");
- nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self));
+ nm_device_activate_schedule_stage2_device_config(NM_DEVICE(self), FALSE);
}
return;
}
@@ -969,11 +973,11 @@ pppoe_reconnect_delay(gpointer user_data)
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
- priv->pppoe_wait_id = 0;
- priv->last_pppoe_time = 0;
+ nm_clear_g_source_inst(&priv->ppp_data.wait_source);
+ priv->ppp_data.last_pppoe_time_msec = 0;
_LOGI(LOGD_DEVICE, "PPPoE reconnect delay complete, resuming connection...");
nm_device_activate_schedule_stage1_device_prepare(NM_DEVICE(self), FALSE);
- return G_SOURCE_REMOVE;
+ return G_SOURCE_CONTINUE;
}
static NMActStageReturn
@@ -1014,21 +1018,24 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
* at least for additional NM_SHUTDOWN_TIMEOUT_MS seconds because
* otherwise after restart the device won't work for the first seconds.
*/
- if (priv->last_pppoe_time != 0) {
- gint32 delay = nm_utils_get_monotonic_timestamp_sec() - priv->last_pppoe_time;
+ if (priv->ppp_data.last_pppoe_time_msec != 0) {
+ gint64 delay =
+ nm_utils_get_monotonic_timestamp_msec() - priv->ppp_data.last_pppoe_time_msec;
- if (delay < PPPOE_RECONNECT_DELAY
+ if (delay < PPPOE_RECONNECT_DELAY_MSEC
&& nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE)) {
- if (priv->pppoe_wait_id == 0) {
+ if (!priv->ppp_data.wait_source) {
_LOGI(LOGD_DEVICE,
- "delaying PPPoE reconnect for %d seconds to ensure peer is ready...",
- delay);
- priv->pppoe_wait_id = g_timeout_add_seconds(delay, pppoe_reconnect_delay, self);
+ "delaying PPPoE reconnect for %d.%03d seconds to ensure peer is ready...",
+ (int) (delay / 1000),
+ (int) (delay % 1000));
+ priv->ppp_data.wait_source =
+ nm_g_timeout_add_source(delay, pppoe_reconnect_delay, self);
}
return NM_ACT_STAGE_RETURN_POSTPONE;
}
- nm_clear_g_source(&priv->pppoe_wait_id);
- priv->last_pppoe_time = 0;
+ nm_clear_g_source_inst(&priv->ppp_data.wait_source);
+ priv->ppp_data.last_pppoe_time_msec = 0;
}
return NM_ACT_STAGE_RETURN_SUCCESS;
@@ -1105,7 +1112,12 @@ carrier_changed(NMSupplicantInterface *iface, GParamSpec *pspec, NMDeviceEtherne
}
/*****************************************************************************/
-/* PPPoE */
+
+/* FIXME(l3cfg:ppp): the way we drive NMPPPManager is more complicated than it
+ * should be. You can see that because NMDevicePPP and NMDeviceAdsl have this
+ * code idential. Also, NMDeviceEthernet does something sufficiently similar
+ * (for handling PPPoE). The API of NMPPPManager should be simplified and handle
+ * more of the complexity. */
static void
ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
@@ -1127,83 +1139,85 @@ ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_d
}
static void
-ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
+ppp_stage3_ready(NMDevice *device)
{
- NMDevice *device = NM_DEVICE(user_data);
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device);
+
+ nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_READY, priv->ppp_data.l3cd_4);
+}
- if (!nm_device_set_ip_ifindex(device, ifindex)) {
+static void
+ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
+{
+ NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data);
+ NMDevice * device = NM_DEVICE(self);
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
+ gs_free char * old_name = NULL;
+ gs_free_error GError *error = NULL;
+
+ if (!nm_device_take_over_link(device, ifindex, &old_name, &error)) {
+ _LOGW(LOGD_DEVICE | LOGD_PPP,
+ "could not take control of link %d: %s",
+ ifindex,
+ error->message);
nm_device_state_changed(device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ return;
}
-}
-static void
-ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
-{
- NMDevice *device = NM_DEVICE(user_data);
+ if (old_name)
+ nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP);
- /* Ignore PPP IP4 events that come in after initial configuration */
- if (nm_device_activate_ip4_state_in_conf(device))
- nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config));
+ priv->stage2_ready_ppp = TRUE;
+ nm_device_activate_schedule_stage2_device_config(device, FALSE);
}
-static NMActStageReturn
-pppoe_stage3_ip4_config_start(NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason)
+static void
+ppp_new_config(NMPPPManager * ppp_manager,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid,
+ gpointer user_data)
{
+ NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data);
NMDevice * device = NM_DEVICE(self);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
- NMSettingPppoe * s_pppoe;
- NMActRequest * req;
- GError * err = NULL;
-
- req = nm_device_get_act_request(device);
-
- g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
- s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE);
-
- g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
+ if (addr_family != AF_INET)
+ return;
- priv->ppp_manager = nm_ppp_manager_create(nm_device_get_iface(device), &err);
+ _LOGT(LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd");
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- nm_device_get_route_table(device, AF_INET),
- nm_device_get_route_metric(device, AF_INET),
- nm_device_get_route_table(device, AF_INET6),
- nm_device_get_route_metric(device, AF_INET6));
- }
+ nm_l3_config_data_reset(&priv->ppp_data.l3cd_4, l3cd);
- if (!priv->ppp_manager
- || !nm_ppp_manager_start(priv->ppp_manager,
- req,
- nm_setting_pppoe_get_username(s_pppoe),
- 30,
- 0,
- &err)) {
- _LOGW(LOGD_DEVICE, "PPPoE failed to start: %s", err->message);
- g_error_free(err);
+ if (nm_device_devip_get_state(device, AF_INET) == NM_DEVICE_IP_STATE_PENDING)
+ ppp_stage3_ready(device);
+}
- g_clear_object(&priv->ppp_manager);
+static void
+ppp_manager_clear(NMDeviceEthernet *self)
+{
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED);
- return NM_ACT_STAGE_RETURN_FAILURE;
+ priv->stage2_ready_ppp = FALSE;
+
+ if (priv->ppp_data.ppp_manager) {
+ g_signal_handlers_disconnect_by_func(priv->ppp_data.ppp_manager,
+ G_CALLBACK(ppp_state_changed),
+ self);
+ g_signal_handlers_disconnect_by_func(priv->ppp_data.ppp_manager,
+ G_CALLBACK(ppp_ifindex_set),
+ self);
+ g_signal_handlers_disconnect_by_func(priv->ppp_data.ppp_manager,
+ G_CALLBACK(ppp_new_config),
+ self);
+
+ nm_ppp_manager_stop(priv->ppp_data.ppp_manager, NULL, NULL, NULL);
+ g_clear_object(&priv->ppp_data.ppp_manager);
}
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_STATE_CHANGED,
- G_CALLBACK(ppp_state_changed),
- self);
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IFINDEX_SET,
- G_CALLBACK(ppp_ifindex_set),
- self);
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_CALLBACK(ppp_ip4_config),
- self);
- return NM_ACT_STAGE_RETURN_POSTPONE;
+ nm_clear_l3cd(&priv->ppp_data.l3cd_4);
}
/*****************************************************************************/
@@ -1351,7 +1365,7 @@ dcb_state(NMDevice *device, gboolean timeout)
nm_clear_g_source(&priv->dcb_timeout_id);
priv->dcb_handle_carrier_changes = FALSE;
priv->dcb_wait = DCB_WAIT_UNKNOWN;
- nm_device_activate_schedule_stage3_ip_config_start(device);
+ nm_device_activate_schedule_stage2_device_config(device, FALSE);
}
break;
default:
@@ -1407,31 +1421,109 @@ found:
static NMActStageReturn
act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
{
- NMDeviceEthernet * self = (NMDeviceEthernet *) device;
+ NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
+ NMConnection * connection;
NMSettingConnection * s_con;
const char * connection_type;
- gboolean do_postpone = FALSE;
NMSettingDcb * s_dcb;
+ NMActRequest * req;
- s_con = nm_device_get_applied_setting(device, NM_TYPE_SETTING_CONNECTION);
+ connection = nm_device_get_applied_connection(device);
+ g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
+ s_con = _nm_connection_get_setting(connection, NM_TYPE_SETTING_CONNECTION);
g_return_val_if_fail(s_con, NM_ACT_STAGE_RETURN_FAILURE);
nm_clear_g_source(&priv->dcb_timeout_id);
priv->dcb_handle_carrier_changes = FALSE;
+ connection_type = nm_setting_connection_get_connection_type(s_con);
+
+ if (!priv->stage2_ready_ppp && nm_streq(connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
+ gs_free_error GError *error = NULL;
+ NMSettingPppoe * s_pppoe;
+ NMSettingPpp * s_ppp;
+
+ if (priv->ppp_data.ppp_manager)
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+
+ s_ppp = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPP);
+ if (s_ppp) {
+ guint32 mtu;
+ guint32 mru;
+ guint32 mxu;
+
+ mtu = nm_setting_ppp_get_mtu(s_ppp);
+ mru = nm_setting_ppp_get_mru(s_ppp);
+ mxu = MAX(mru, mtu);
+ if (mxu) {
+ _LOGD(LOGD_PPP,
+ "set MTU to %u (PPP interface MRU %u, MTU %u)",
+ mxu + PPPOE_ENCAP_OVERHEAD,
+ mru,
+ mtu);
+ nm_platform_link_set_mtu(nm_device_get_platform(device),
+ nm_device_get_ifindex(device),
+ mxu + PPPOE_ENCAP_OVERHEAD);
+ }
+ }
+
+ req = nm_device_get_act_request(device);
+ g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
+
+ s_pppoe = _nm_connection_get_setting(connection, NM_TYPE_SETTING_PPPOE);
+ g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
+
+ priv->ppp_data.ppp_manager = nm_ppp_manager_create(nm_device_get_iface(device), &error);
+
+ if (!priv->ppp_data.ppp_manager) {
+ _LOGW(LOGD_DEVICE, "PPPoE failed to create manager: %s", error->message);
+ *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+
+ g_signal_connect(priv->ppp_data.ppp_manager,
+ NM_PPP_MANAGER_SIGNAL_STATE_CHANGED,
+ G_CALLBACK(ppp_state_changed),
+ self);
+ g_signal_connect(priv->ppp_data.ppp_manager,
+ NM_PPP_MANAGER_SIGNAL_IFINDEX_SET,
+ G_CALLBACK(ppp_ifindex_set),
+ self);
+ g_signal_connect(priv->ppp_data.ppp_manager,
+ NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
+ G_CALLBACK(ppp_new_config),
+ self);
+
+ if (!nm_ppp_manager_start(priv->ppp_data.ppp_manager,
+ req,
+ nm_setting_pppoe_get_username(s_pppoe),
+ 30,
+ 0,
+ &error)) {
+ _LOGW(LOGD_DEVICE, "PPPoE failed to start: %s", error->message);
+ ppp_manager_clear(self);
+ *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+ }
+
+ priv->stage2_ready_ppp = TRUE;
+
/* 802.1x has to run before any IP configuration since the 802.1x auth
* process opens the port up for normal traffic.
*/
- connection_type = nm_setting_connection_get_connection_type(s_con);
if (nm_streq(connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
NMSetting8021x *security;
security = nm_device_get_applied_setting(device, NM_TYPE_SETTING_802_1X);
if (security) {
- /* FIXME: for now 802.1x is mutually exclusive with DCB */
+ /* FIXME: we always return from this. stage2 must be re-entrant, and
+ * process all the necessary steps. Just returning for 8021x is wrong. */
if (!nm_device_has_carrier(NM_DEVICE(self))) {
_LOGD(LOGD_DEVICE | LOGD_ETHER,
"delay supplicant initialization until carrier goes up");
@@ -1450,7 +1542,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
/* DCB and FCoE setup */
s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_DCB);
- if (s_dcb) {
+ if (!priv->stage2_ready_dcb && s_dcb) {
/* lldpad really really wants the carrier to be up */
if (nm_platform_link_is_connected(nm_device_get_platform(device),
nm_device_get_ifindex(device))) {
@@ -1465,76 +1557,53 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
}
priv->dcb_handle_carrier_changes = TRUE;
- do_postpone = TRUE;
- }
-
- /* PPPoE setup */
- if (nm_connection_is_type(nm_device_get_applied_connection(device),
- NM_SETTING_PPPOE_SETTING_NAME)) {
- NMSettingPpp *s_ppp;
-
- s_ppp = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPP);
- if (s_ppp) {
- guint32 mtu;
- guint32 mru;
- guint32 mxu;
-
- mtu = nm_setting_ppp_get_mtu(s_ppp);
- mru = nm_setting_ppp_get_mru(s_ppp);
- mxu = MAX(mru, mtu);
- if (mxu) {
- _LOGD(LOGD_PPP,
- "set MTU to %u (PPP interface MRU %u, MTU %u)",
- mxu + PPPOE_ENCAP_OVERHEAD,
- mru,
- mtu);
- nm_platform_link_set_mtu(nm_device_get_platform(device),
- nm_device_get_ifindex(device),
- mxu + PPPOE_ENCAP_OVERHEAD);
- }
- }
+ return NM_ACT_STAGE_RETURN_POSTPONE;
}
- return do_postpone ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_SUCCESS;
+ return NM_ACT_STAGE_RETURN_SUCCESS;
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static guint32
+get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force)
{
- NMSettingConnection *s_con;
- const char * connection_type;
- int ifindex;
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device);
- ifindex = nm_device_get_ifindex(device);
+ /* MTU only set for plain ethernet */
+ if (priv->ppp_data.ppp_manager)
+ return 0;
- if (ifindex <= 0)
- return NM_ACT_STAGE_RETURN_FAILURE;
+ return nm_device_get_configured_mtu_for_wired(device, out_source, out_force);
+}
- if (addr_family == AF_INET) {
- s_con = nm_device_get_applied_setting(device, NM_TYPE_SETTING_CONNECTION);
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
+{
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device);
- g_return_val_if_fail(s_con, NM_ACT_STAGE_RETURN_FAILURE);
+ if (!priv->ppp_data.ppp_manager)
+ return;
- connection_type = nm_setting_connection_get_connection_type(s_con);
- if (!strcmp(connection_type, NM_SETTING_PPPOE_SETTING_NAME))
- return pppoe_stage3_ip4_config_start(NM_DEVICE_ETHERNET(device), out_failure_reason);
+ if (!NM_IS_IPv4(addr_family)) {
+ /* TODO: IPv6 is not implemented/handled. */
+ return;
}
- return NM_DEVICE_CLASS(nm_device_ethernet_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
-}
-
-static guint32
-get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force)
-{
- /* MTU only set for plain ethernet */
- if (NM_DEVICE_ETHERNET_GET_PRIVATE(device)->ppp_manager)
- return 0;
-
- return nm_device_get_configured_mtu_for_wired(device, out_source, out_force);
+ switch (nm_device_devip_get_state(device, addr_family)) {
+ case NM_DEVICE_IP_STATE_NONE:
+ if (priv->ppp_data.l3cd_4) {
+ ppp_stage3_ready(device);
+ return;
+ }
+ nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL);
+ return;
+ case NM_DEVICE_IP_STATE_PENDING:
+ nm_assert(!priv->ppp_data.l3cd_4);
+ return;
+ case NM_DEVICE_IP_STATE_FAILED:
+ case NM_DEVICE_IP_STATE_READY:
+ return;
+ }
+ nm_assert_not_reached();
}
static void
@@ -1546,19 +1615,17 @@ deactivate(NMDevice *device)
GError * error = NULL;
int ifindex;
- nm_clear_g_source(&priv->pppoe_wait_id);
+ nm_clear_g_source_inst(&priv->ppp_data.wait_source);
nm_clear_g_signal_handler(self, &priv->carrier_id);
- if (priv->ppp_manager) {
- nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL);
- g_clear_object(&priv->ppp_manager);
- }
+ ppp_manager_clear(self);
supplicant_interface_release(self);
priv->dcb_wait = DCB_WAIT_UNKNOWN;
nm_clear_g_source(&priv->dcb_timeout_id);
priv->dcb_handle_carrier_changes = FALSE;
+ priv->stage2_ready_dcb = FALSE;
/* Tear down DCB/FCoE if it was enabled */
s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_DCB);
@@ -1571,7 +1638,7 @@ deactivate(NMDevice *device)
/* Set last PPPoE connection time */
if (nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE))
- priv->last_pppoe_time = nm_utils_get_monotonic_timestamp_sec();
+ priv->ppp_data.last_pppoe_time_msec = nm_utils_get_monotonic_timestamp_msec();
ifindex = nm_device_get_ifindex(device);
if (ifindex > 0 && priv->ethtool_prev_set) {
@@ -1933,7 +2000,7 @@ dispose(GObject *object)
supplicant_interface_release(self);
- nm_clear_g_source(&priv->pppoe_wait_id);
+ nm_clear_g_source_inst(&priv->ppp_data.wait_source);
nm_clear_g_source(&priv->dcb_timeout_id);
@@ -2032,7 +2099,7 @@ nm_device_ethernet_class_init(NMDeviceEthernetClass *klass)
device_class->act_stage1_prepare = act_stage1_prepare;
device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE;
device_class->act_stage2_config = act_stage2_config;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
device_class->get_configured_mtu = get_configured_mtu;
device_class->deactivate = deactivate;
device_class->get_s390_subchannels = get_s390_subchannels;
diff --git a/src/core/devices/nm-device-infiniband.c b/src/core/devices/nm-device-infiniband.c
index df14dfa838..57b7698cb3 100644
--- a/src/core/devices/nm-device-infiniband.c
+++ b/src/core/devices/nm-device-infiniband.c
@@ -13,7 +13,6 @@
#include "NetworkManagerUtils.h"
#include "nm-device-private.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
diff --git a/src/core/devices/nm-device-ip-tunnel.c b/src/core/devices/nm-device-ip-tunnel.c
index fe2e20239a..59653a685d 100644
--- a/src/core/devices/nm-device-ip-tunnel.c
+++ b/src/core/devices/nm-device-ip-tunnel.c
@@ -22,7 +22,6 @@
#include "libnm-core-intern/nm-core-internal.h"
#include "settings/nm-settings.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#define _NMLOG_DEVICE_TYPE NMDeviceIPTunnel
#include "nm-device-logging.h"
diff --git a/src/core/devices/nm-device-macsec.c b/src/core/devices/nm-device-macsec.c
index 51b7225bbf..7fa0779b52 100644
--- a/src/core/devices/nm-device-macsec.c
+++ b/src/core/devices/nm-device-macsec.c
@@ -409,7 +409,7 @@ supplicant_iface_state_is_completed(NMDeviceMacsec *self, NMSupplicantInterfaceS
*/
if (nm_device_get_state(NM_DEVICE(self)) == NM_DEVICE_STATE_CONFIG) {
_LOGI(LOGD_DEVICE, "Activation: Stage 2 of 5 (Device Configure) successful.");
- nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self));
+ nm_device_activate_schedule_stage3_ip_config(NM_DEVICE(self), FALSE);
}
return;
}
diff --git a/src/core/devices/nm-device-macvlan.c b/src/core/devices/nm-device-macvlan.c
index 937ba9e4e4..27be9f0023 100644
--- a/src/core/devices/nm-device-macvlan.c
+++ b/src/core/devices/nm-device-macvlan.c
@@ -19,7 +19,6 @@
#include "nm-setting-macvlan.h"
#include "nm-setting-wired.h"
#include "nm-active-connection.h"
-#include "nm-ip4-config.h"
#include "nm-utils.h"
#define _NMLOG_DEVICE_TYPE NMDeviceMacvlan
diff --git a/src/core/devices/nm-device-ppp.c b/src/core/devices/nm-device-ppp.c
index 04051bece5..afc4f12de6 100644
--- a/src/core/devices/nm-device-ppp.c
+++ b/src/core/devices/nm-device-ppp.c
@@ -7,7 +7,7 @@
#include "nm-device-ppp.h"
-#include "nm-ip4-config.h"
+#include "nm-l3-config-data.h"
#include "nm-act-request.h"
#include "nm-device-factory.h"
#include "nm-device-private.h"
@@ -24,8 +24,9 @@
/*****************************************************************************/
typedef struct _NMDevicePppPrivate {
- NMPPPManager *ppp_manager;
- NMIP4Config * ip4_config;
+ NMPPPManager * ppp_manager;
+ const NML3ConfigData *l3cd_4;
+ bool stage2_ready_ppp : 1;
} NMDevicePppPrivate;
struct _NMDevicePpp {
@@ -48,6 +49,14 @@ get_generic_capabilities(NMDevice *device)
return NM_DEVICE_CAP_IS_SOFTWARE;
}
+/*****************************************************************************/
+
+/* FIXME(l3cfg:ppp): the way we drive NMPPPManager is more complicated than it
+ * should be. You can see that because NMDevicePPP and NMDeviceAdsl have this
+ * code idential. Also, NMDeviceEthernet does something sufficiently similar
+ * (for handling PPPoE). The API of NMPPPManager should be simplified and handle
+ * more of the complexity. */
+
static void
ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
{
@@ -68,12 +77,21 @@ ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_d
}
static void
+ppp_stage3_ready(NMDevice *device)
+{
+ NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(device);
+
+ nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_READY, priv->l3cd_4);
+}
+
+static void
ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
{
- NMDevice * device = NM_DEVICE(user_data);
- NMDevicePpp * self = NM_DEVICE_PPP(device);
- gs_free char *old_name = NULL;
- gs_free_error GError *error = NULL;
+ NMDevicePpp * self = NM_DEVICE_PPP(user_data);
+ NMDevice * device = NM_DEVICE(self);
+ NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
+ gs_free char * old_name = NULL;
+ gs_free_error GError *error = NULL;
if (!nm_device_take_over_link(device, ifindex, &old_name, &error)) {
_LOGW(LOGD_DEVICE | LOGD_PPP,
@@ -89,39 +107,55 @@ ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpoin
if (old_name)
nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP);
- nm_device_activate_schedule_stage3_ip_config_start(device);
+ priv->stage2_ready_ppp = TRUE;
+ nm_device_activate_schedule_stage2_device_config(device, FALSE);
}
static void
-_ppp_ip4_config_handle(NMDevicePpp *self)
+ppp_new_config(NMPPPManager * ppp_manager,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid,
+ gpointer user_data)
{
+ NMDevicePpp * self = NM_DEVICE_PPP(user_data);
NMDevice * device = NM_DEVICE(self);
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
- if (!priv->ip4_config)
+ if (addr_family != AF_INET)
return;
- if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG
- && nm_device_activate_ip4_state_in_conf(device)) {
- nm_device_activate_schedule_ip_config_result(
- device,
- AF_INET,
- NM_IP_CONFIG_CAST(g_steal_pointer(&priv->ip4_config)));
- return;
- }
+ _LOGT(LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd");
+
+ nm_l3_config_data_reset(&priv->l3cd_4, l3cd);
+
+ if (nm_device_devip_get_state(device, AF_INET) == NM_DEVICE_IP_STATE_PENDING)
+ ppp_stage3_ready(device);
}
static void
-ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
+ppp_manager_clear(NMDevicePpp *self)
{
- NMDevicePpp * self = NM_DEVICE_PPP(user_data);
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
- _LOGT(LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd");
- nm_g_object_ref_set(&priv->ip4_config, config);
- _ppp_ip4_config_handle(self);
+ priv->stage2_ready_ppp = FALSE;
+
+ if (priv->ppp_manager) {
+ g_signal_handlers_disconnect_by_func(priv->ppp_manager,
+ G_CALLBACK(ppp_state_changed),
+ self);
+ g_signal_handlers_disconnect_by_func(priv->ppp_manager, G_CALLBACK(ppp_ifindex_set), self);
+ g_signal_handlers_disconnect_by_func(priv->ppp_manager, G_CALLBACK(ppp_new_config), self);
+
+ nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL);
+ g_clear_object(&priv->ppp_manager);
+ }
+
+ nm_clear_l3cd(&priv->l3cd_4);
}
+/*****************************************************************************/
+
static gboolean
check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error)
{
@@ -149,85 +183,84 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
NMSettingPppoe * s_pppoe;
NMActRequest * req;
- GError * error = NULL;
-
- req = nm_device_get_act_request(device);
- g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
-
- s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE);
- g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
-
- g_clear_object(&priv->ip4_config);
- priv->ppp_manager = nm_ppp_manager_create(nm_setting_pppoe_get_parent(s_pppoe), &error);
-
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- nm_device_get_route_table(device, AF_INET),
- nm_device_get_route_metric(device, AF_INET),
- nm_device_get_route_table(device, AF_INET6),
- nm_device_get_route_metric(device, AF_INET6));
- }
+ if (!priv->stage2_ready_ppp) {
+ gs_free_error GError *error = NULL;
+
+ if (priv->ppp_manager)
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+
+ req = nm_device_get_act_request(device);
+ g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
+
+ s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE);
+ g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
+
+ priv->ppp_manager = nm_ppp_manager_create(nm_setting_pppoe_get_parent(s_pppoe), &error);
+
+ if (!priv->ppp_manager) {
+ _LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message);
+ *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+
+ g_signal_connect(priv->ppp_manager,
+ NM_PPP_MANAGER_SIGNAL_STATE_CHANGED,
+ G_CALLBACK(ppp_state_changed),
+ self);
+ g_signal_connect(priv->ppp_manager,
+ NM_PPP_MANAGER_SIGNAL_IFINDEX_SET,
+ G_CALLBACK(ppp_ifindex_set),
+ self);
+ g_signal_connect(priv->ppp_manager,
+ NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
+ G_CALLBACK(ppp_new_config),
+ self);
+
+ if (!nm_ppp_manager_start(priv->ppp_manager,
+ req,
+ nm_setting_pppoe_get_username(s_pppoe),
+ 30,
+ 0,
+ &error)) {
+ _LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message);
+ ppp_manager_clear(self);
+ *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
- if (!priv->ppp_manager
- || !nm_ppp_manager_start(priv->ppp_manager,
- req,
- nm_setting_pppoe_get_username(s_pppoe),
- 30,
- 0,
- &error)) {
- _LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message);
- g_error_free(error);
-
- g_clear_object(&priv->ppp_manager);
-
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED);
- return NM_ACT_STAGE_RETURN_FAILURE;
+ return NM_ACT_STAGE_RETURN_POSTPONE;
}
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_STATE_CHANGED,
- G_CALLBACK(ppp_state_changed),
- self);
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IFINDEX_SET,
- G_CALLBACK(ppp_ifindex_set),
- self);
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_CALLBACK(ppp_ip4_config),
- self);
- return NM_ACT_STAGE_RETURN_POSTPONE;
-}
-
-static gboolean
-_schedule_ip_config_result(gpointer user_data)
-{
- gs_unref_object NMDevicePpp *self = user_data;
-
- _ppp_ip4_config_handle(self);
- return G_SOURCE_REMOVE;
+ return NM_ACT_STAGE_RETURN_SUCCESS;
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
{
- if (addr_family == AF_INET) {
- NMDevicePpp * self = NM_DEVICE_PPP(device);
- NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
+ NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(device);
- if (priv->ip4_config)
- nm_g_idle_add(_schedule_ip_config_result, g_object_ref(self));
-
- /* Wait IPCP termination */
- return NM_ACT_STAGE_RETURN_POSTPONE;
+ if (!NM_IS_IPv4(addr_family)) {
+ /* TODO: IPv6 is not implemented/handled. */
+ return;
}
- return NM_DEVICE_CLASS(nm_device_ppp_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ switch (nm_device_devip_get_state(device, addr_family)) {
+ case NM_DEVICE_IP_STATE_NONE:
+ if (priv->l3cd_4) {
+ ppp_stage3_ready(device);
+ return;
+ }
+ nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL);
+ return;
+ case NM_DEVICE_IP_STATE_PENDING:
+ nm_assert(!priv->l3cd_4);
+ return;
+ case NM_DEVICE_IP_STATE_FAILED:
+ case NM_DEVICE_IP_STATE_READY:
+ return;
+ }
+ nm_assert_not_reached();
}
static gboolean
@@ -260,17 +293,13 @@ create_and_realize(NMDevice * device,
static void
deactivate(NMDevice *device)
{
- NMDevicePpp * self = NM_DEVICE_PPP(device);
- NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
-
- if (priv->ppp_manager) {
- nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL);
- g_clear_object(&priv->ppp_manager);
- }
+ NMDevicePpp *self = NM_DEVICE_PPP(device);
- g_clear_object(&priv->ip4_config);
+ ppp_manager_clear(self);
}
+/*****************************************************************************/
+
static void
nm_device_ppp_init(NMDevicePpp *self)
{}
@@ -278,10 +307,9 @@ nm_device_ppp_init(NMDevicePpp *self)
static void
dispose(GObject *object)
{
- NMDevicePpp * self = NM_DEVICE_PPP(object);
- NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
+ NMDevicePpp *self = NM_DEVICE_PPP(object);
- g_clear_object(&priv->ip4_config);
+ ppp_manager_clear(self);
G_OBJECT_CLASS(nm_device_ppp_parent_class)->dispose(object);
}
@@ -306,7 +334,7 @@ nm_device_ppp_class_init(NMDevicePppClass *klass)
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_PPP);
device_class->act_stage2_config = act_stage2_config;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
device_class->check_connection_compatible = check_connection_compatible;
device_class->create_and_realize = create_and_realize;
device_class->deactivate = deactivate;
diff --git a/src/core/devices/nm-device-private.h b/src/core/devices/nm-device-private.h
index b55e8b4380..fc2bc04d60 100644
--- a/src/core/devices/nm-device-private.h
+++ b/src/core/devices/nm-device-private.h
@@ -8,6 +8,7 @@
#define __NETWORKMANAGER_DEVICE_PRIVATE_H__
#include "nm-device.h"
+#include "nm-l3-config-data.h"
/* This file should only be used by subclasses of NMDevice */
@@ -34,8 +35,6 @@ enum NMActStageReturn {
#define NM_DEVICE_CAP_INTERNAL_MASK 0xc0000000
-void nm_device_arp_announce(NMDevice *self);
-
NMSettings *nm_device_get_settings(NMDevice *self);
NMManager *nm_device_get_manager(NMDevice *self);
@@ -44,10 +43,6 @@ gboolean nm_device_set_ip_ifindex(NMDevice *self, int ifindex);
gboolean nm_device_set_ip_iface(NMDevice *self, const char *iface);
-void nm_device_activate_schedule_stage3_ip_config_start(NMDevice *device);
-
-gboolean nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family);
-
gboolean nm_device_bring_up(NMDevice *self, gboolean wait, gboolean *no_firmware);
void nm_device_take_down(NMDevice *self, gboolean block);
@@ -65,52 +60,7 @@ void nm_device_set_firmware_missing(NMDevice *self, gboolean missing);
void nm_device_activate_schedule_stage1_device_prepare(NMDevice *device, gboolean do_sync);
void nm_device_activate_schedule_stage2_device_config(NMDevice *device, gboolean do_sync);
-
-void
-nm_device_activate_schedule_ip_config_result(NMDevice *device, int addr_family, NMIPConfig *config);
-
-void nm_device_activate_schedule_ip_config_timeout(NMDevice *device, int addr_family);
-
-NMDeviceIPState nm_device_activate_get_ip_state(NMDevice *self, int addr_family);
-
-static inline gboolean
-nm_device_activate_ip4_state_in_conf(NMDevice *self)
-{
- return nm_device_activate_get_ip_state(self, AF_INET) == NM_DEVICE_IP_STATE_CONF;
-}
-
-static inline gboolean
-nm_device_activate_ip4_state_in_wait(NMDevice *self)
-{
- return nm_device_activate_get_ip_state(self, AF_INET) == NM_DEVICE_IP_STATE_WAIT;
-}
-
-static inline gboolean
-nm_device_activate_ip4_state_done(NMDevice *self)
-{
- return nm_device_activate_get_ip_state(self, AF_INET) == NM_DEVICE_IP_STATE_DONE;
-}
-
-static inline gboolean
-nm_device_activate_ip6_state_in_conf(NMDevice *self)
-{
- return nm_device_activate_get_ip_state(self, AF_INET6) == NM_DEVICE_IP_STATE_CONF;
-}
-
-static inline gboolean
-nm_device_activate_ip6_state_in_wait(NMDevice *self)
-{
- return nm_device_activate_get_ip_state(self, AF_INET6) == NM_DEVICE_IP_STATE_WAIT;
-}
-
-static inline gboolean
-nm_device_activate_ip6_state_done(NMDevice *self)
-{
- return nm_device_activate_get_ip_state(self, AF_INET6) == NM_DEVICE_IP_STATE_DONE;
-}
-
-gboolean nm_device_dhcp4_renew(NMDevice *device, gboolean release);
-gboolean nm_device_dhcp6_renew(NMDevice *device, gboolean release);
+void nm_device_activate_schedule_stage3_ip_config(NMDevice *device, gboolean do_sync);
void nm_device_recheck_available_connections(NMDevice *device);
@@ -126,25 +76,54 @@ void nm_device_queue_recheck_available(NMDevice * device,
NMDeviceStateReason available_reason,
NMDeviceStateReason unavailable_reason);
-void nm_device_set_dev2_ip_config(NMDevice *device, int addr_family, NMIPConfig *config);
-
gboolean nm_device_hw_addr_is_explict(NMDevice *device);
-void nm_device_ip_method_failed(NMDevice *self, int addr_family, NMDeviceStateReason reason);
+NMDeviceIPState nm_device_devip_get_state(NMDevice *self, int addr_family);
+
+void nm_device_devip_set_state_full(NMDevice * self,
+ int addr_family,
+ NMDeviceIPState ip_state,
+ const NML3ConfigData *l3cd,
+ NMDeviceStateReason failed_reason);
+
+static inline void
+nm_device_devip_set_state(NMDevice * self,
+ int addr_family,
+ NMDeviceIPState ip_state,
+ const NML3ConfigData *l3cd)
+{
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert_addr_family_or_unspec(addr_family);
+ nm_assert(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd));
+ nm_assert(NM_IN_SET(ip_state, NM_DEVICE_IP_STATE_PENDING, NM_DEVICE_IP_STATE_READY));
+
+ nm_device_devip_set_state_full(self, addr_family, ip_state, l3cd, NM_DEVICE_STATE_REASON_NONE);
+}
+
+static inline void
+nm_device_devip_set_failed(NMDevice *self, int addr_family, NMDeviceStateReason reason)
+{
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert_addr_family_or_unspec(addr_family);
+ nm_assert(reason != NM_DEVICE_STATE_REASON_NONE);
+
+ nm_device_devip_set_state_full(self,
+ addr_family,
+ NM_DEVICE_IP_STATE_FAILED,
+ NULL,
+ NM_DEVICE_STATE_REASON_NONE);
+}
gboolean nm_device_sysctl_ip_conf_set(NMDevice * self,
int addr_family,
const char *property,
const char *value);
-NMIP4Config *nm_device_ip4_config_new(NMDevice *self);
-
-NMIP6Config *nm_device_ip6_config_new(NMDevice *self);
-
-NMIPConfig *nm_device_ip_config_new(NMDevice *self, int addr_family);
-
NML3ConfigData *nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source);
+const NML3ConfigData *nm_device_create_l3_config_data_from_connection(NMDevice * self,
+ NMConnection *connection);
+
/*****************************************************************************/
gint64 nm_device_get_configured_mtu_from_connection_default(NMDevice * self,
diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c
index 0ab08f65b5..1f6a427636 100644
--- a/src/core/devices/nm-device-tun.c
+++ b/src/core/devices/nm-device-tun.c
@@ -13,7 +13,6 @@
#include "nm-act-request.h"
#include "nm-device-private.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-tun.h"
diff --git a/src/core/devices/nm-device-utils.c b/src/core/devices/nm-device-utils.c
index df3f3eb110..4a2cffdfd6 100644
--- a/src/core/devices/nm-device-utils.c
+++ b/src/core/devices/nm-device-utils.c
@@ -151,10 +151,9 @@ NM_UTILS_LOOKUP_STR_DEFINE(nm_device_ip_state_to_string,
NMDeviceIPState,
NM_UTILS_LOOKUP_DEFAULT_WARN("unknown"),
NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_NONE, "none"),
- NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_WAIT, "wait"),
- NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_CONF, "conf"),
- NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_DONE, "done"),
- NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_FAIL, "fail"), );
+ NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_PENDING, "pending"),
+ NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_READY, "done"),
+ NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_FAILED, "fail"), );
/*****************************************************************************/
diff --git a/src/core/devices/nm-device-utils.h b/src/core/devices/nm-device-utils.h
index 7200b0ea2c..759e610568 100644
--- a/src/core/devices/nm-device-utils.h
+++ b/src/core/devices/nm-device-utils.h
@@ -73,20 +73,17 @@ const char *nm_device_sys_iface_state_to_string(NMDeviceSysIfaceState sys_iface_
/*****************************************************************************/
-typedef enum {
+typedef enum _nm_packed {
NM_DEVICE_IP_STATE_NONE,
- NM_DEVICE_IP_STATE_WAIT,
- NM_DEVICE_IP_STATE_CONF,
- NM_DEVICE_IP_STATE_DONE,
- NM_DEVICE_IP_STATE_FAIL,
+ NM_DEVICE_IP_STATE_PENDING,
+ NM_DEVICE_IP_STATE_READY,
+ NM_DEVICE_IP_STATE_FAILED,
} NMDeviceIPState;
const char *nm_device_ip_state_to_string(NMDeviceIPState ip_state);
/*****************************************************************************/
-/*****************************************************************************/
-
void nm_device_resolve_address(int addr_family,
gconstpointer address,
GCancellable * cancellable,
diff --git a/src/core/devices/nm-device-vlan.c b/src/core/devices/nm-device-vlan.c
index d1e5741170..c1902d5eea 100644
--- a/src/core/devices/nm-device-vlan.c
+++ b/src/core/devices/nm-device-vlan.c
@@ -15,7 +15,6 @@
#include "nm-device-private.h"
#include "settings/nm-settings.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-manager.h"
@@ -85,11 +84,11 @@ parent_mtu_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_data
static void
parent_hwaddr_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_data)
{
- NMDevice * device = NM_DEVICE(user_data);
- NMDeviceVlan * self = NM_DEVICE_VLAN(device);
- NMConnection * connection;
- const char * new_mac, *old_mac;
- NMSettingIPConfig *s_ip6;
+ NMDevice * device = NM_DEVICE(user_data);
+ NMDeviceVlan *self = NM_DEVICE_VLAN(device);
+ NMConnection *connection;
+ const char * old_mac;
+ const char * new_mac;
/* Never touch assumed devices */
if (nm_device_sys_iface_state_is_external_or_assume(device))
@@ -113,13 +112,10 @@ parent_hwaddr_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_d
NM_PRINT_FMT_QUOTE_STRING(new_mac));
if (new_mac) {
nm_device_hw_addr_set(device, new_mac, "vlan-parent", TRUE);
- nm_device_arp_announce(device);
/* When changing the hw address the interface is taken down,
* removing the IPv6 configuration; reapply it.
*/
- s_ip6 = nm_connection_get_setting_ip6_config(connection);
- if (s_ip6)
- nm_device_reactivate_ip_config(device, AF_INET6, s_ip6, s_ip6);
+ nm_device_l3cfg_commit(device, NM_L3_CFG_COMMIT_TYPE_REAPPLY, FALSE);
}
}
diff --git a/src/core/devices/nm-device-vxlan.c b/src/core/devices/nm-device-vxlan.c
index fcd6950b88..329cc3febb 100644
--- a/src/core/devices/nm-device-vxlan.c
+++ b/src/core/devices/nm-device-vxlan.c
@@ -16,7 +16,6 @@
#include "nm-setting-wired.h"
#include "settings/nm-settings.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
#include "libnm-core-intern/nm-core-internal.h"
diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c
index f129478f7f..de715264ce 100644
--- a/src/core/devices/nm-device-wireguard.c
+++ b/src/core/devices/nm-device-wireguard.c
@@ -12,6 +12,7 @@
#include "nm-setting-wireguard.h"
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
+#include "nm-l3-config-data.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-glib-aux/nm-secret-utils.h"
#include "nm-device-private.h"
@@ -1625,19 +1626,19 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
return ret;
}
-static NMIPConfig *
+static const NML3ConfigData *
_get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family)
{
- NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
- gs_unref_object NMIPConfig *ip_config = NULL;
- NMConnection * connection;
- NMSettingWireGuard * s_wg;
- guint n_peers;
- guint i;
- int ip_ifindex;
- guint32 route_metric;
- guint32 route_table_coerced;
- gboolean auto_default_route_enabled;
+ NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMConnection * connection;
+ NMSettingWireGuard * s_wg;
+ guint n_peers;
+ guint i;
+ int ip_ifindex;
+ guint32 route_metric;
+ guint32 route_table_coerced;
+ gboolean auto_default_route_enabled;
_auto_default_route_init(self);
@@ -1715,11 +1716,10 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family)
continue;
}
- if (!ip_config) {
- ip_config = nm_device_ip_config_new(NM_DEVICE(self), addr_family);
- nm_ip_config_set_config_flags(ip_config,
- NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES,
- 0);
+ if (!l3cd) {
+ l3cd = nm_device_create_l3_config_data(NM_DEVICE(self), NM_IP_CONFIG_SOURCE_USER);
+ nm_l3_config_data_set_flags(l3cd,
+ NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES);
}
nm_utils_ipx_address_clear_host_address(addr_family, &addrbin, NULL, prefix);
@@ -1754,27 +1754,23 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family)
};
}
- nm_ip_config_add_route(ip_config, &rt.rx, NULL);
+ nm_l3_config_data_add_route(l3cd, addr_family, NULL, &rt.rx);
}
}
- return g_steal_pointer(&ip_config);
+ if (!l3cd)
+ return NULL;
+
+ return nm_l3_config_data_seal(g_steal_pointer(&l3cd));
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
{
- gs_unref_object NMIPConfig *ip_config = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
- ip_config = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family);
-
- nm_device_set_dev2_ip_config(device, addr_family, ip_config);
-
- return NM_DEVICE_CLASS(nm_device_wireguard_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ l3cd = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family);
+ nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd);
}
static guint32
@@ -1864,11 +1860,9 @@ can_reapply_change(NMDevice * device,
static void
reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_new)
{
- NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device);
- NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
- gs_unref_object NMIPConfig *ip4_config = NULL;
- gs_unref_object NMIPConfig *ip6_config = NULL;
- NMDeviceState state = nm_device_get_state(device);
+ NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device);
+ NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
+ NMDeviceState state = nm_device_get_state(device);
NM_DEVICE_CLASS(nm_device_wireguard_parent_class)->reapply_connection(device, con_old, con_new);
@@ -1878,11 +1872,14 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne
}
if (state >= NM_DEVICE_STATE_IP_CONFIG) {
- ip4_config = _get_dev2_ip_config(self, AF_INET);
- ip6_config = _get_dev2_ip_config(self, AF_INET6);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_4 = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_6 = NULL;
+
+ l3cd_4 = _get_dev2_ip_config(self, AF_INET);
+ l3cd_6 = _get_dev2_ip_config(self, AF_INET6);
- nm_device_set_dev2_ip_config(device, AF_INET, ip4_config);
- nm_device_set_dev2_ip_config(device, AF_INET6, ip6_config);
+ nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_READY, l3cd_4);
+ nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_READY, l3cd_6);
}
}
@@ -2025,7 +2022,7 @@ nm_device_wireguard_class_init(NMDeviceWireGuardClass *klass)
device_class->create_and_realize = create_and_realize;
device_class->act_stage2_config = act_stage2_config;
device_class->act_stage2_config_also_for_external_or_assume = TRUE;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->link_changed = link_changed;
device_class->update_connection = update_connection;
diff --git a/src/core/devices/nm-device-wpan.c b/src/core/devices/nm-device-wpan.c
index 9bc43a850d..ed5bcbde4d 100644
--- a/src/core/devices/nm-device-wpan.c
+++ b/src/core/devices/nm-device-wpan.c
@@ -14,7 +14,6 @@
#include "nm-act-request.h"
#include "nm-device-private.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-wpan.h"
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 7faec23c8e..a9b77fe05c 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -34,6 +34,8 @@
#include "nm-device-private.h"
#include "nm-l3cfg.h"
#include "nm-l3-config-data.h"
+#include "nm-l3-ipv4ll.h"
+#include "nm-l3-ipv6ll.h"
#include "NetworkManagerUtils.h"
#include "nm-manager.h"
#include "libnm-platform/nm-platform.h"
@@ -42,14 +44,13 @@
#include "libnm-platform/nmp-rules-manager.h"
#include "ndisc/nm-ndisc.h"
#include "ndisc/nm-lndp-ndisc.h"
+
#include "dhcp/nm-dhcp-manager.h"
#include "dhcp/nm-dhcp-utils.h"
#include "nm-act-request.h"
-#include "nm-proxy-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "nm-pacrunner-manager.h"
#include "dnsmasq/nm-dnsmasq-manager.h"
+#include "nm-ip-config.h"
#include "nm-dhcp-config.h"
#include "nm-rfkill-manager.h"
#include "nm-firewall-utils.h"
@@ -66,7 +67,6 @@
#include "nm-config.h"
#include "c-list/src/c-list.h"
#include "dns/nm-dns-manager.h"
-#include "nm-acd-manager.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-systemd-core/nm-sd.h"
#include "nm-lldp-listener.h"
@@ -86,19 +86,7 @@
#define DEFAULT_AUTOCONNECT TRUE
-static guint32
-dhcp_grace_period_from_timeout(guint32 timeout)
-{
-#define DHCP_GRACE_PERIOD_MULTIPLIER 2U
-
- nm_assert(timeout > 0);
- nm_assert(timeout < G_MAXINT32);
-
- if (timeout < G_MAXUINT32 / DHCP_GRACE_PERIOD_MULTIPLIER)
- return timeout * DHCP_GRACE_PERIOD_MULTIPLIER;
-
- return G_MAXUINT32;
-}
+#define GRACE_PERIOD_MULTIPLIER 2U
#define CARRIER_WAIT_TIME_MS 6000
#define CARRIER_WAIT_TIME_AFTER_MTU_MS 10000
@@ -117,6 +105,13 @@ typedef enum {
CLEANUP_TYPE_DECONFIGURE,
} CleanupType;
+typedef enum _nm_packed {
+ ADDR_METHOD_STATE_DISABLED,
+ ADDR_METHOD_STATE_PENDING,
+ ADDR_METHOD_STATE_GOOD,
+ ADDR_METHOD_STATE_FAILED,
+} AddrMethodState;
+
typedef struct {
CList lst_slave;
NMDevice *slave;
@@ -139,28 +134,61 @@ typedef struct {
NMOptionBool autoprobe;
} SriovOp;
-typedef void (*AcdCallback)(NMDevice *, NMIP4Config **, gboolean);
-
typedef enum {
/* The various NML3ConfigData types that we track explicitly. Note that
* their relative order matters: higher numbers in this enum means more
* important (and during merge overwrites other settings). */
+
L3_CONFIG_DATA_TYPE_LL_4,
+ L3_CONFIG_DATA_TYPE_LL_6,
+
+#define L3_CONFIG_DATA_TYPE_LL_X(IS_IPv4) \
+ ((IS_IPv4) ? L3_CONFIG_DATA_TYPE_LL_4 : L3_CONFIG_DATA_TYPE_LL_6)
+
L3_CONFIG_DATA_TYPE_AC_6,
+ L3_CONFIG_DATA_TYPE_PD_6,
+
L3_CONFIG_DATA_TYPE_DHCP_4,
L3_CONFIG_DATA_TYPE_DHCP_6,
- L3_CONFIG_DATA_TYPE_DEV_4,
- L3_CONFIG_DATA_TYPE_DEV_6,
- L3_CONFIG_DATA_TYPE_SETTING,
+
+#define L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4) \
+ ((IS_IPv4) ? L3_CONFIG_DATA_TYPE_DHCP_4 : L3_CONFIG_DATA_TYPE_DHCP_6)
+
+ L3_CONFIG_DATA_TYPE_SHARED_4,
+ L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC,
+ L3_CONFIG_DATA_TYPE_DEVIP_4,
+ L3_CONFIG_DATA_TYPE_DEVIP_6,
+
+#define L3_CONFIG_DATA_TYPE_DEVIP(addr_family) \
+ ({ \
+ L3ConfigDataType _t; \
+ \
+ switch (addr_family) { \
+ case AF_INET: \
+ _t = L3_CONFIG_DATA_TYPE_DEVIP_4; \
+ break; \
+ case AF_INET6: \
+ _t = L3_CONFIG_DATA_TYPE_DEVIP_6; \
+ break; \
+ default: \
+ nm_assert_not_reached(); \
+ /* fall-through */ \
+ case AF_UNSPEC: \
+ _t = L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC; \
+ break; \
+ } \
+ \
+ _t; \
+ })
+
+ L3_CONFIG_DATA_TYPE_MANUALIP,
+
_L3_CONFIG_DATA_TYPE_NUM,
_L3_CONFIG_DATA_TYPE_NONE,
+ _L3_CONFIG_DATA_TYPE_ACD_ONLY,
} L3ConfigDataType;
-typedef struct {
- AcdCallback callback;
- NMDevice * device;
- NMIP4Config **configs;
-} AcdData;
+G_STATIC_ASSERT(NM_L3CFG_CONFIG_PRIORITY_IPV4LL == L3_CONFIG_DATA_TYPE_LL_4);
typedef enum {
HW_ADDR_TYPE_UNSET = 0,
@@ -177,19 +205,73 @@ typedef enum {
} FirewallState;
typedef struct {
- NMIPConfig *orig; /* the original configuration applied to the device */
- NMIPConfig *current; /* configuration after external changes. NULL means
- * that the original configuration didn't change. */
-} AppliedConfig;
+ NMIPConfig *ip_config;
+} L3IPData;
+
+typedef struct {
+ GSource *check_async_source;
+ GSource *req_timeout_source;
+ union {
+ const NMDeviceIPState state;
+ NMDeviceIPState state_;
+ };
+ bool wait_for_carrier : 1;
+ bool wait_for_ports : 1;
+ bool is_disabled : 1;
+ bool is_ignore : 1;
+ bool do_reapply : 1;
+} IPStateData;
typedef struct {
- NMDhcpClient *client;
- NMDhcpConfig *config;
- gulong notify_sigid;
- guint grace_id;
- bool grace_pending : 1;
- bool was_active : 1;
-} DhcpData;
+ NMDhcpClient * client;
+ NMDhcpConfig * config;
+ gulong notify_sigid;
+ NMDeviceIPState state;
+ union {
+ struct {
+ } v4;
+ struct {
+ guint needed_prefixes;
+ NMNDiscDHCPLevel mode;
+ } v6;
+ };
+} IPDhcpStateData;
+
+typedef struct {
+ NMDeviceIPState state;
+ NMDeviceStateReason failed_reason;
+} IPDevStateData;
+
+typedef struct {
+ NMDeviceIPState state;
+ union {
+ struct {
+ NMDnsMasqManager * dnsmasq_manager;
+ NMNetnsSharedIPHandle *shared_ip_handle;
+ NMFirewallConfig * firewall_config;
+ gulong dnsmasq_state_id;
+ } v4;
+ struct {
+ } v6;
+ };
+} IPSharedStateData;
+
+typedef struct {
+ NMDeviceIPState state;
+ union {
+ struct {
+ NML3IPv4LL * ipv4ll;
+ NML3IPv4LLRegistration *ipv4ll_registation;
+ GSource * timeout_source;
+ } v4;
+ struct {
+ NML3IPv6LL * ipv6ll;
+ GSource * retry_source;
+ NML3IPv6LLState llstate;
+ struct in6_addr lladdr;
+ } v6;
+ };
+} IPLLStateData;
struct _NMDeviceConnectivityHandle {
CList concheck_lst;
@@ -234,8 +316,7 @@ typedef struct {
enum {
STATE_CHANGED,
AUTOCONNECT_ALLOWED,
- IP4_CONFIG_CHANGED,
- IP6_CONFIG_CHANGED,
+ L3CD_CHANGED,
IP6_PREFIX_DELEGATED,
IP6_SUBNET_NEEDED,
REMOVED,
@@ -260,6 +341,9 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice,
PROP_IP4_ADDRESS,
PROP_IP4_CONFIG,
PROP_DHCP4_CONFIG,
+
+#define PROP_DHCPX_CONFIG(IS_IPv4) ((IS_IPv4) ? PROP_DHCP4_CONFIG : PROP_DHCP6_CONFIG)
+
PROP_IP6_CONFIG,
PROP_DHCP6_CONFIG,
PROP_STATE,
@@ -293,8 +377,6 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice,
PROP_INTERFACE_FLAGS, );
typedef struct _NMDevicePrivate {
- bool in_state_changed;
-
guint device_link_changed_id;
guint device_ip_link_changed_id;
@@ -308,22 +390,12 @@ typedef struct _NMDevicePrivate {
NMDeviceStateReason reason;
} queued_state;
- union {
- struct {
- guint queued_ip_config_id_6;
- guint queued_ip_config_id_4;
- };
- guint queued_ip_config_id_x[2];
- };
-
struct {
const char **arr;
guint len;
guint alloc;
} pending_actions;
- GSList *dad6_failed_addrs;
-
NMDBusTrackObjPath parent_device;
char *udi;
@@ -339,15 +411,33 @@ typedef struct _NMDevicePrivate {
};
union {
+ NML3Cfg *const l3cfg;
+ NML3Cfg * l3cfg_;
+ };
+
+ union {
+ struct {
+ L3IPData l3ipdata_6;
+ L3IPData l3ipdata_4;
+ };
+ L3IPData l3ipdata_x[2];
+ };
+
+ NML3CfgCommitTypeHandle *l3cfg_commit_type;
+
+ union {
const int ifindex;
int ifindex_;
};
+
union {
const int ip_ifindex;
int ip_ifindex_;
};
- NMNetnsSharedIPHandle *shared_ip_handle;
+ union {
+ const NML3ConfigData *d;
+ } l3cds[_L3_CONFIG_DATA_TYPE_NUM];
int parent_ifindex;
@@ -370,9 +460,6 @@ typedef struct _NMDevicePrivate {
bool real : 1;
- bool update_ip_config_completed_v4 : 1;
- bool update_ip_config_completed_v6 : 1;
-
NMDeviceType type;
char * type_desc;
NMLinkType link_type;
@@ -386,6 +473,8 @@ typedef struct _NMDevicePrivate {
bool
hw_addr_perm_fake : 1; /* whether the permanent HW address could not be read and is a fake */
+ guint8 in_state_changed : 4;
+
NMUtilsStableType current_stable_id_type : 3;
bool nm_owned : 1; /* whether the device is a device owned and created by NM */
@@ -413,21 +502,8 @@ typedef struct _NMDevicePrivate {
bool queued_act_request_is_waiting_for_carrier : 1;
NMDBusTrackObjPath act_request;
- union {
- struct {
- guint activation_source_id_6;
- guint activation_source_id_4; /* for layer2 and IPv4. */
- };
- guint activation_source_id_x[2];
- };
-
- union {
- struct {
- ActivationHandleFunc activation_source_func_6;
- ActivationHandleFunc activation_source_func_4; /* for layer2 and IPv4. */
- };
- ActivationHandleFunc activation_source_func_x[2];
- };
+ GSource * activation_idle_source;
+ ActivationHandleFunc activation_func;
guint recheck_assume_id;
@@ -451,7 +527,7 @@ typedef struct _NMDevicePrivate {
gulong config_changed_id;
gulong ifindex_changed_id;
guint32 mtu;
- guint32 ip6_mtu;
+ guint32 ip6_mtu; /* FIXME(l3cfg) */
guint32 mtu_initial;
guint32 ip6_mtu_initial;
NMDeviceMtuSource mtu_source;
@@ -468,6 +544,14 @@ typedef struct _NMDevicePrivate {
gint64 carrier_wait_until_ms;
union {
+ struct {
+ NML3ConfigMergeFlags l3config_merge_flags_6;
+ NML3ConfigMergeFlags l3config_merge_flags_4;
+ };
+ NML3ConfigMergeFlags l3config_merge_flags_x[2];
+ };
+
+ union {
const NMDeviceSysIfaceState sys_iface_state;
NMDeviceSysIfaceState sys_iface_state_;
};
@@ -477,9 +561,6 @@ typedef struct _NMDevicePrivate {
bool up : 1; /* IFF_UP */
- bool v4_commit_first_time : 1;
- bool v6_commit_first_time : 1;
-
bool default_route_metric_penalty_ip4_has : 1;
bool default_route_metric_penalty_ip6_has : 1;
@@ -495,102 +576,86 @@ typedef struct _NMDevicePrivate {
bool is_enslaved : 1;
- bool ipv6ll_handle : 1; /* TRUE if NM handles the device's IPv6LL address */
- bool ipv6ll_has : 1;
- bool ndisc_started : 1;
bool device_link_changed_down : 1;
bool concheck_rp_filter_checked : 1;
- NMDeviceStageState stage1_sriov_state : 3;
-
- bool ip_config_started : 1;
bool tc_committed : 1;
- char *current_stable_id;
+ NMDeviceStageState stage1_sriov_state : 3;
- union {
- struct {
- GSource *ip_req_timeout_source_6;
- GSource *ip_req_timeout_source_4;
- };
- GSource *ip_req_timeout_source_x[2];
- };
+ char *current_stable_id;
- /* Proxy Configuration */
- NMProxyConfig * proxy_config;
NMPacrunnerConfId *pacrunner_conf_id;
- /* IP configuration info. Combined config from VPN, settings, and device */
+ struct {
+ union {
+ const NMDeviceIPState state;
+ NMDeviceIPState state_;
+ };
+ } ip_data;
+
union {
struct {
- NMIP6Config *ip_config_6;
- NMIP4Config *ip_config_4;
+ IPStateData ip_data_6;
+ IPStateData ip_data_4;
};
- NMIPConfig *ip_config_x[2];
+ IPStateData ip_data_x[2];
};
- /* Config from DHCP, PPP, LLv4, etc */
- AppliedConfig dev_ip_config_4;
+ struct {
+ NMDeviceIPState state;
+ } ipmanual_data;
- /* config from the setting */
union {
struct {
- NMIP6Config *con_ip_config_6;
- NMIP4Config *con_ip_config_4;
+ IPDhcpStateData ipdhcp_data_6;
+ IPDhcpStateData ipdhcp_data_4;
};
- NMIPConfig *con_ip_config_x[2];
+ IPDhcpStateData ipdhcp_data_x[2];
};
- /* Stuff added outside NM */
+ struct {
+ NMNDisc * ndisc;
+ GSource * ndisc_grace_source;
+ gulong ndisc_changed_id;
+ gulong ndisc_timeout_id;
+ NMDeviceIPState state;
+ } ipac6_data;
+
union {
struct {
- NMIP6Config *ext_ip_config_6;
- NMIP4Config *ext_ip_config_4;
+ IPLLStateData ipll_data_6;
+ IPLLStateData ipll_data_4;
};
- NMIPConfig *ext_ip_config_x[2];
+ IPLLStateData ipll_data_x[2];
};
- /* VPNs which use this device */
union {
struct {
- GSList *vpn_configs_6;
- GSList *vpn_configs_4;
+ IPSharedStateData ipshared_data_6;
+ IPSharedStateData ipshared_data_4;
};
- GSList *vpn_configs_x[2];
+ IPSharedStateData ipshared_data_x[2];
};
- /* Extra device configuration, injected by the subclass of NMDevice.
- * This is used for example by NMDeviceModem for WWAN configuration. */
union {
struct {
- AppliedConfig dev2_ip_config_6;
- AppliedConfig dev2_ip_config_4;
+ IPDevStateData ipdev_data_6;
+ IPDevStateData ipdev_data_4;
};
- AppliedConfig dev2_ip_config_x[2];
+ IPDevStateData ipdev_data_x[2];
};
- /* DHCPv4 tracking */
- struct {
- char *pac_url;
- } dhcp4;
+ IPDevStateData ipdev_data_unspec;
struct {
- /* IP6 config from DHCP */
- AppliedConfig ip6_config;
- /* Event ID of the current IP6 config from DHCP */
- char * event_id;
- NMNDiscDHCPLevel mode;
- guint needed_prefixes;
- } dhcp6;
+ /* If we set the addrgenmode6, this records the previously set value. */
+ guint8 previous_mode_val;
- union {
- struct {
- DhcpData dhcp_data_6;
- DhcpData dhcp_data_4;
- };
- DhcpData dhcp_data_x[2];
- };
+ /* whether @previous_mode_val is set. */
+ bool previous_mode_has : 1;
+ } addrgenmode6_data;
struct {
NMLogDomain log_domain;
@@ -602,58 +667,15 @@ typedef struct _NMDevicePrivate {
guint deadline;
} gw_ping;
- /* dnsmasq stuff for shared connections */
- NMDnsMasqManager *dnsmasq_manager;
- gulong dnsmasq_state_id;
-
/* Firewall */
FirewallState fw_state : 4;
NMFirewalldManager * fw_mgr;
NMFirewalldManagerCallId *fw_call;
- /* IPv4LL stuff */
- sd_ipv4ll *ipv4ll;
- guint ipv4ll_timeout;
- guint rt6_temporary_not_available_id;
-
- /* IPv4 DAD stuff */
- struct {
- GSList * dad_list;
- NMAcdManager *announcing;
- } acd;
-
- union {
- struct {
- const NMDeviceIPState ip_state_6;
- const NMDeviceIPState ip_state_4;
- };
- union {
- const NMDeviceIPState ip_state_x[2];
- NMDeviceIPState ip_state_x_[2];
- };
- };
-
- AppliedConfig ac_ip6_config; /* config from IPv6 autoconfiguration */
- NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */
- NMIP6Config * dad6_ip6_config;
- struct in6_addr ipv6ll_addr;
-
- GHashTable *rt6_temporary_not_available;
-
- NMNDisc * ndisc;
- gulong ndisc_changed_id;
- gulong ndisc_timeout_id;
- NMSettingIP6ConfigPrivacy ndisc_use_tempaddr;
-
- guint linklocal6_timeout_id;
- guint8 linklocal6_dad_counter;
-
GHashTable *ip6_saved_properties;
EthtoolState *ethtool_state;
- gboolean needs_ip6_subnet;
-
/* master interface for bridge/bond/team slave */
NMDevice *master;
gulong master_ready_id;
@@ -709,6 +731,8 @@ typedef struct _NMDevicePrivate {
bool mtu_force_set_done : 1;
+ bool needs_ip6_subnet : 1;
+
NMOptionBool promisc_reset;
} NMDevicePrivate;
@@ -718,59 +742,83 @@ G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT)
/*****************************************************************************/
+static NMSettingConnectionMdns _prop_get_connection_mdns(NMDevice *self);
+static NMSettingConnectionLlmnr _prop_get_connection_llmnr(NMDevice *self);
+
static const NMDBusInterfaceInfoExtended interface_info_device;
static const GDBusSignalInfo signal_info_state_changed;
-static void nm_device_set_proxy_config(NMDevice *self, const char *pac_url);
+static void _dev_l3_cfg_commit(NMDevice *self, gboolean do_sync);
-static gboolean update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs);
-
-static gboolean nm_device_set_ip_config(NMDevice * self,
- int addr_family,
- NMIPConfig *config,
- gboolean commit,
- GPtrArray * ip4_dev_route_blacklist);
-
-static gboolean ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit);
+static void _dev_l3_cfg_commit_type_reset(NMDevice *self);
static gboolean nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure);
static void nm_device_slave_notify_enslave(NMDevice *self, gboolean success);
static void nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason);
-static void addrconf6_start_with_link_ready(NMDevice *self);
-static gboolean linklocal6_start(NMDevice *self);
+static void _dev_ipll6_start(NMDevice *self);
-static guint32 default_route_metric_penalty_get(NMDevice *self, int addr_family);
+static void _dev_ipac6_start_continue(NMDevice *self);
-static guint _prop_get_ipv4_dad_timeout(NMDevice *self);
+static guint32 _dev_default_route_metric_penalty_get(NMDevice *self, int addr_family);
-static NMIP6Config *dad6_get_pending_addresses(NMDevice *self);
+static guint32 _prop_get_ipv4_dad_timeout(NMDevice *self);
static void _carrier_wait_check_queued_act_request(NMDevice *self);
static gint64 _get_carrier_wait_ms(NMDevice *self);
+static GBytes *_prop_get_ipv6_dhcp_duid(NMDevice * self,
+ NMConnection *connection,
+ GBytes * hwaddr,
+ gboolean * out_enforce);
+
static const char *_activation_func_to_string(ActivationHandleFunc func);
static void
_set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, gboolean quitting);
-static void queued_state_clear(NMDevice *device);
-static gboolean queued_ip4_config_change(gpointer user_data);
-static gboolean queued_ip6_config_change(gpointer user_data);
-static void ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data);
-static gboolean ip_config_valid(NMDeviceState state);
-static NMActStageReturn dhcp4_start(NMDevice *self);
-static gboolean dhcp6_start(NMDevice *self, gboolean wait_for_ll);
-static void nm_device_start_ip_check(NMDevice *self);
-static void realize_start_setup(NMDevice * self,
- const NMPlatformLink *plink,
- gboolean assume_state_guess_assume,
- const char * assume_state_connection_uuid,
- gboolean set_nm_owned,
- NMUnmanFlagOp unmanaged_user_explicit,
- gboolean force_platform_init);
-static void _set_mtu(NMDevice *self, guint32 mtu);
-static void _commit_mtu(NMDevice *self, const NMIP4Config *config);
-static void _cancel_activation(NMDevice *self);
+static void queued_state_clear(NMDevice *device);
+static void ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data);
+static void nm_device_start_ip_check(NMDevice *self);
+static void realize_start_setup(NMDevice * self,
+ const NMPlatformLink *plink,
+ gboolean assume_state_guess_assume,
+ const char * assume_state_connection_uuid,
+ gboolean set_nm_owned,
+ NMUnmanFlagOp unmanaged_user_explicit,
+ gboolean force_platform_init);
+static void _set_mtu(NMDevice *self, guint32 mtu);
+static void _commit_mtu(NMDevice *self);
+static void _cancel_activation(NMDevice *self);
+
+static void _dev_ipll4_notify_event(NMDevice *self);
+
+static void _dev_ip_state_check(NMDevice *self, int addr_family);
+
+static void _dev_ipmanual_check_ready(NMDevice *self);
+
+static void
+_dev_ipdhcpx_cleanup(NMDevice *self, int addr_family, gboolean reset_dhcp_config, gboolean release);
+
+static void _dev_ip_state_check_async(NMDevice *self, int addr_family);
+
+static void _dev_ipdhcpx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state);
+
+static void _dev_ipdhcpx_restart(NMDevice *self, int addr_family, gboolean release);
+
+static void _dev_ipdhcpx_handle_accept(NMDevice *self, int addr_family, const NML3ConfigData *l3cd);
+
+static gboolean
+_dev_ipac6_grace_period_start(NMDevice *self, guint32 timeout_sec, gboolean force_restart);
+
+static void _dev_ipac6_start(NMDevice *self);
+
+static void _dev_unamanged_check_external_down(NMDevice *self, gboolean only_if_unmanaged);
+
+static void _dev_ipshared4_start(NMDevice *self);
+
+static void _dev_ipshared6_start(NMDevice *self);
+
+static void _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type);
static void concheck_update_state(NMDevice * self,
int addr_family,
@@ -780,8 +828,79 @@ static void concheck_update_state(NMDevice * self,
static void sriov_op_cb(GError *error, gpointer user_data);
static void device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice *self);
-static gboolean device_link_changed(NMDevice *self);
-static void check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update);
+static gboolean device_link_changed(gpointer user_data);
+
+/*****************************************************************************/
+
+#define _NMLOG_addr_family(level, prefix, addr_family, fmt, ...) \
+ G_STMT_START \
+ { \
+ const int _addr_family2 = (addr_family); \
+ \
+ _NMLOG(level, \
+ (_addr_family2 == AF_UNSPEC ? LOGD_IP : LOGD_IPX(NM_IS_IPv4(_addr_family2))), \
+ "" prefix "%s: " fmt, \
+ nm_utils_addr_family_to_str(_addr_family2), \
+ ##__VA_ARGS__); \
+ } \
+ G_STMT_END
+
+#define _NMLOG_ip(level, ...) _NMLOG_addr_family(level, "ip", __VA_ARGS__)
+#define _LOGT_ip(...) _NMLOG_ip(LOGL_TRACE, __VA_ARGS__)
+#define _LOGD_ip(...) _NMLOG_ip(LOGL_DEBUG, __VA_ARGS__)
+#define _LOGI_ip(...) _NMLOG_ip(LOGL_INFO, __VA_ARGS__)
+#define _LOGW_ip(...) _NMLOG_ip(LOGL_WARN, __VA_ARGS__)
+
+#define _NMLOG_ipll(level, ...) _NMLOG_addr_family(level, "ip:ll", __VA_ARGS__)
+#define _LOGT_ipll(...) _NMLOG_ipll(LOGL_TRACE, __VA_ARGS__)
+#define _LOGD_ipll(...) _NMLOG_ipll(LOGL_DEBUG, __VA_ARGS__)
+#define _LOGI_ipll(...) _NMLOG_ipll(LOGL_INFO, __VA_ARGS__)
+#define _LOGW_ipll(...) _NMLOG_ipll(LOGL_WARN, __VA_ARGS__)
+
+#define _NMLOG_ipdev(level, ...) _NMLOG_addr_family(level, "ip:dev", __VA_ARGS__)
+#define _LOGT_ipdev(...) _NMLOG_ipdev(LOGL_TRACE, __VA_ARGS__)
+#define _LOGD_ipdev(...) _NMLOG_ipdev(LOGL_DEBUG, __VA_ARGS__)
+#define _LOGI_ipdev(...) _NMLOG_ipdev(LOGL_INFO, __VA_ARGS__)
+#define _LOGW_ipdev(...) _NMLOG_ipdev(LOGL_WARN, __VA_ARGS__)
+
+#define _NMLOG_ipdhcp(level, ...) _NMLOG_addr_family(level, "ip:dhcp", __VA_ARGS__)
+#define _LOGT_ipdhcp(...) _NMLOG_ipdhcp(LOGL_TRACE, __VA_ARGS__)
+#define _LOGD_ipdhcp(...) _NMLOG_ipdhcp(LOGL_DEBUG, __VA_ARGS__)
+#define _LOGI_ipdhcp(...) _NMLOG_ipdhcp(LOGL_INFO, __VA_ARGS__)
+#define _LOGW_ipdhcp(...) _NMLOG_ipdhcp(LOGL_WARN, __VA_ARGS__)
+
+#define _NMLOG_ipshared(level, ...) _NMLOG_addr_family(level, "ip:shared", __VA_ARGS__)
+#define _LOGT_ipshared(...) _NMLOG_ipshared(LOGL_TRACE, __VA_ARGS__)
+#define _LOGD_ipshared(...) _NMLOG_ipshared(LOGL_DEBUG, __VA_ARGS__)
+#define _LOGI_ipshared(...) _NMLOG_ipshared(LOGL_INFO, __VA_ARGS__)
+#define _LOGW_ipshared(...) _NMLOG_ipshared(LOGL_WARN, __VA_ARGS__)
+
+#define _NMLOG_ipac6(level, ...) _NMLOG_addr_family(level, "ip:ac6", AF_UNSPEC, __VA_ARGS__)
+#define _LOGT_ipac6(...) _NMLOG_ipac6(LOGL_TRACE, __VA_ARGS__)
+#define _LOGD_ipac6(...) _NMLOG_ipac6(LOGL_DEBUG, __VA_ARGS__)
+#define _LOGI_ipac6(...) _NMLOG_ipac6(LOGL_INFO, __VA_ARGS__)
+#define _LOGW_ipac6(...) _NMLOG_ipac6(LOGL_WARN, __VA_ARGS__)
+
+#define _NMLOG_ipmanual(level, ...) _NMLOG_addr_family(level, "ip:manual", AF_UNSPEC, __VA_ARGS__)
+#define _LOGT_ipmanual(...) _NMLOG_ipmanual(LOGL_TRACE, __VA_ARGS__)
+#define _LOGD_ipmanual(...) _NMLOG_ipmanual(LOGL_DEBUG, __VA_ARGS__)
+#define _LOGI_ipmanual(...) _NMLOG_ipmanual(LOGL_INFO, __VA_ARGS__)
+#define _LOGW_ipmanual(...) _NMLOG_ipmanual(LOGL_WARN, __VA_ARGS__)
+
+/*****************************************************************************/
+
+#define _CACHED_BOOL(cached_value, cmd) \
+ ({ \
+ NMTernary *const _cached_value = (cached_value); \
+ \
+ nm_assert(_cached_value); \
+ nm_assert_is_ternary(*_cached_value); \
+ \
+ if (*_cached_value == NM_TERNARY_DEFAULT) \
+ *_cached_value = !!(cmd); \
+ \
+ !!(*_cached_value); \
+ })
/*****************************************************************************/
@@ -1309,7 +1428,7 @@ _prop_get_connection_lldp(NMDevice *self)
return lldp == NM_SETTING_CONNECTION_LLDP_ENABLE_RX;
}
-static guint
+static guint32
_prop_get_ipv4_dad_timeout(NMDevice *self)
{
NMConnection * connection;
@@ -1321,6 +1440,9 @@ _prop_get_ipv4_dad_timeout(NMDevice *self)
s_ip4 = nm_connection_get_setting_ip4_config(connection);
if (s_ip4)
timeout = nm_setting_ip_config_get_dad_timeout(s_ip4);
+
+ nm_assert(timeout >= -1 && timeout <= NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX);
+
if (timeout >= 0)
return timeout;
@@ -1337,8 +1459,8 @@ _prop_get_ipvx_dhcp_timeout(NMDevice *self, int addr_family)
{
NMDeviceClass *klass;
NMConnection * connection;
- int timeout_i;
guint32 timeout;
+ int timeout_i;
nm_assert(NM_IS_DEVICE(self));
nm_assert_addr_family(addr_family);
@@ -1381,6 +1503,37 @@ out:
}
static guint32
+_prop_get_ipvx_dns_priority(NMDevice *self, int addr_family)
+{
+ NMConnection * connection;
+ NMSettingIPConfig *s_ip;
+ int prio = 0;
+
+ connection = nm_device_get_applied_connection(self);
+ s_ip = nm_connection_get_setting_ip_config(connection, addr_family);
+ if (s_ip)
+ prio = nm_setting_ip_config_get_dns_priority(s_ip);
+
+ if (prio == 0) {
+ prio = nm_config_data_get_connection_default_int64(
+ NM_CONFIG_GET_DATA,
+ NM_IS_IPv4(addr_family) ? NM_CON_DEFAULT("ipv4.dns-priority")
+ : NM_CON_DEFAULT("ipv6.dns-priority"),
+ self,
+ G_MININT32,
+ G_MAXINT32,
+ 0);
+ if (prio == 0) {
+ prio = nm_device_is_vpn(self) ? NM_DNS_PRIORITY_DEFAULT_VPN
+ : NM_DNS_PRIORITY_DEFAULT_NORMAL;
+ }
+ }
+
+ nm_assert(prio != 0);
+ return prio;
+}
+
+static guint32
_prop_get_ipvx_required_timeout(NMDevice *self, int addr_family)
{
NMConnection * connection;
@@ -1414,6 +1567,25 @@ _prop_get_ipvx_required_timeout(NMDevice *self, int addr_family)
0);
}
+static gboolean
+_prop_get_ipvx_may_fail(NMDevice *self, int addr_family)
+{
+ NMConnection * connection;
+ NMSettingIPConfig *s_ip = NULL;
+
+ connection = nm_device_get_applied_connection(self);
+ if (connection)
+ s_ip = nm_connection_get_setting_ip_config(connection, addr_family);
+
+ return !s_ip || nm_setting_ip_config_get_may_fail(s_ip);
+}
+
+static gboolean
+_prop_get_ipvx_may_fail_cached(NMDevice *self, int addr_family, NMTernary *cache)
+{
+ return _CACHED_BOOL(cache, _prop_get_ipvx_may_fail(self, addr_family));
+}
+
/**
* _prop_get_ipvx_dhcp_iaid:
* @self: the #NMDevice
@@ -2390,27 +2562,6 @@ concheck_get_mgr(NMDevice *self)
return priv->concheck_mgr;
}
-NMIP4Config *
-nm_device_ip4_config_new(NMDevice *self)
-{
- return nm_ip4_config_new(nm_device_get_multi_index(self), nm_device_get_ip_ifindex(self));
-}
-
-NMIP6Config *
-nm_device_ip6_config_new(NMDevice *self)
-{
- return nm_ip6_config_new(nm_device_get_multi_index(self), nm_device_get_ip_ifindex(self));
-}
-
-NMIPConfig *
-nm_device_ip_config_new(NMDevice *self, int addr_family)
-{
- nm_assert_addr_family(addr_family);
-
- return NM_IS_IPv4(addr_family) ? (gpointer) nm_device_ip4_config_new(self)
- : (gpointer) nm_device_ip6_config_new(self);
-}
-
NML3ConfigData *
nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source)
{
@@ -2425,98 +2576,27 @@ nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source)
return nm_l3_config_data_new(nm_device_get_multi_index(self), ifindex, source);
}
-static void
-applied_config_clear(AppliedConfig *config)
-{
- g_clear_object(&config->current);
- g_clear_object(&config->orig);
-}
-
-static void
-applied_config_init(AppliedConfig *config, gpointer ip_config)
+const NML3ConfigData *
+nm_device_create_l3_config_data_from_connection(NMDevice *self, NMConnection *connection)
{
- nm_assert(!ip_config || (!config->orig && !config->current)
- || nm_ip_config_get_addr_family(ip_config)
- == nm_ip_config_get_addr_family(config->orig ?: config->current));
- nm_assert(!ip_config || NM_IS_IP_CONFIG(ip_config));
+ NML3ConfigData *l3cd;
+ int ifindex;
- nm_g_object_ref(ip_config);
- applied_config_clear(config);
- config->orig = ip_config;
-}
-
-static void
-applied_config_init_new(AppliedConfig *config, NMDevice *self, int addr_family)
-{
- gs_unref_object NMIPConfig *c = nm_device_ip_config_new(self, addr_family);
-
- applied_config_init(config, c);
-}
-
-static NMIPConfig *
-applied_config_get_current(AppliedConfig *config)
-{
- return config->current ?: config->orig;
-}
-
-static void
-applied_config_add_address(AppliedConfig *config, const NMPlatformIPAddress *address)
-{
- if (config->orig)
- nm_ip_config_add_address(config->orig, address);
- else
- nm_assert(!config->current);
-
- if (config->current)
- nm_ip_config_add_address(config->current, address);
-}
-
-static void
-applied_config_add_nameserver(AppliedConfig *config, const NMIPAddr *ns)
-{
- if (config->orig)
- nm_ip_config_add_nameserver(config->orig, ns);
- else
- nm_assert(!config->current);
-
- if (config->current)
- nm_ip_config_add_nameserver(config->current, ns);
-}
-
-static void
-applied_config_add_search(AppliedConfig *config, const char *new)
-{
- if (config->orig)
- nm_ip_config_add_search(config->orig, new);
- else
- nm_assert(!config->current);
-
- if (config->current)
- nm_ip_config_add_search(config->current, new);
-}
-
-static void
-applied_config_reset_searches(AppliedConfig *config)
-{
- if (config->orig)
- nm_ip_config_reset_searches(config->orig);
- else
- nm_assert(!config->current);
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert(!connection || NM_IS_CONNECTION(connection));
- if (config->current)
- nm_ip_config_reset_searches(config->current);
-}
+ if (!connection)
+ return NULL;
-static void
-applied_config_reset_nameservers(AppliedConfig *config)
-{
- if (config->orig)
- nm_ip_config_reset_nameservers(config->orig);
- else
- nm_assert(!config->current);
+ ifindex = nm_device_get_ip_ifindex(self);
+ if (ifindex <= 0)
+ g_return_val_if_reached(NULL);
- if (config->current)
- nm_ip_config_reset_nameservers(config->current);
+ l3cd =
+ nm_l3_config_data_new_from_connection(nm_device_get_multi_index(self), ifindex, connection);
+ nm_l3_config_data_set_mdns(l3cd, _prop_get_connection_mdns(self));
+ nm_l3_config_data_set_llmnr(l3cd, _prop_get_connection_llmnr(self));
+ return l3cd;
}
/*****************************************************************************/
@@ -2562,6 +2642,7 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st
nm_device_sys_iface_state_to_string(priv->sys_iface_state),
nm_device_sys_iface_state_to_string(sys_iface_state));
priv->sys_iface_state_ = sys_iface_state;
+ _dev_l3_cfg_commit_type_reset(self);
}
/* this function only sets a flag, no immediate actions are initiated.
@@ -2674,33 +2755,6 @@ nm_device_assume_state_reset(NMDevice *self)
/*****************************************************************************/
-static void
-init_ip_config_dns_priority(NMDevice *self, NMIPConfig *config)
-{
- const char *property;
- int priority;
-
- property = (nm_ip_config_get_addr_family(config) == AF_INET)
- ? NM_CON_DEFAULT("ipv4.dns-priority")
- : NM_CON_DEFAULT("ipv6.dns-priority");
-
- priority = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA,
- property,
- self,
- G_MININT,
- G_MAXINT,
- 0);
-
- if (priority == 0) {
- priority =
- nm_device_is_vpn(self) ? NM_DNS_PRIORITY_DEFAULT_VPN : NM_DNS_PRIORITY_DEFAULT_NORMAL;
- }
-
- nm_ip_config_set_dns_priority(config, priority);
-}
-
-/*****************************************************************************/
-
static char *
nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property)
{
@@ -2837,93 +2891,878 @@ _add_capabilities(NMDevice *self, NMDeviceCapabilities capabilities)
/*****************************************************************************/
+static void
+_dev_ip_state_req_timeout_cancel(NMDevice *self, int addr_family)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
+ if (addr_family == AF_UNSPEC) {
+ _dev_ip_state_req_timeout_cancel(self, AF_INET);
+ _dev_ip_state_req_timeout_cancel(self, AF_INET6);
+ return;
+ }
+
+ if (nm_clear_g_source_inst(&priv->ip_data_x[NM_IS_IPv4(addr_family)].req_timeout_source))
+ _LOGD_ip(addr_family, "required-timeout: cancelled");
+}
+
static gboolean
-ip_required_timeout_x(NMDevice *self, int addr_family)
+_dev_ip_state_req_timeout_cb_x(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- _LOGD(LOGD_CORE,
- "required-timeout expired for IPv%c",
- nm_utils_addr_family_to_char(addr_family));
- nm_clear_g_source_inst(&priv->ip_req_timeout_source_x[NM_IS_IPv4(addr_family)]);
- check_ip_state(self, FALSE, TRUE);
+ _LOGD_ip(addr_family, "required-timeout: expired");
+ nm_clear_g_source_inst(&priv->ip_data_x[NM_IS_IPv4(addr_family)].req_timeout_source);
+ _dev_ip_state_check(self, addr_family);
return G_SOURCE_CONTINUE;
}
static gboolean
-ip_required_timeout_4(gpointer data)
+_dev_ip_state_req_timeout_cb_4(gpointer user_data)
{
- return ip_required_timeout_x(data, AF_INET);
+ return _dev_ip_state_req_timeout_cb_x(user_data, AF_INET);
}
static gboolean
-ip_required_timeout_6(gpointer data)
+_dev_ip_state_req_timeout_cb_6(gpointer user_data)
{
- return ip_required_timeout_x(data, AF_INET6);
+ return _dev_ip_state_req_timeout_cb_x(user_data, AF_INET6);
}
static void
-_set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state)
+_dev_ip_state_req_timeout_schedule(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
- guint timeout_msec;
- int v4;
+ guint32 timeout_msec;
+ char buf[32];
- nm_assert_addr_family(addr_family);
+ nm_assert(!priv->ip_data_x[IS_IPv4].req_timeout_source);
- if (new_state == NM_DEVICE_IP_STATE_CONF && !priv->ip_config_started) {
- /* Start the required-timeout timers when one of IPv4/IPv6
- * enters the CONF state. This means that if there is no carrier and
- * ipv4.method=auto,ipv6.method=manual, the timeout for IPv4 will
- * start as soon as connection is activated, even if DHCPv4 did not
- * start yet.
- */
- priv->ip_config_started = TRUE;
+ timeout_msec = _prop_get_ipvx_required_timeout(self, addr_family);
+ if (timeout_msec == 0) {
+ _LOGD_ip(addr_family, "required-timeout: disabled");
+ return;
+ }
- for (v4 = 1; v4 >= 0; v4--) {
- char buf[32];
+ _LOGD_ip(addr_family,
+ "required-timeout: started (%s msec)",
+ timeout_msec == G_MAXINT32 ? "∞" : nm_sprintf_buf(buf, "%u", timeout_msec));
- nm_assert(!priv->ip_req_timeout_source_x[v4]);
- if ((timeout_msec = _prop_get_ipvx_required_timeout(self, v4 ? AF_INET : AF_INET6))) {
- _LOGD(LOGD_CORE,
- "required-timeout in %s msec for IPv%c",
- timeout_msec == G_MAXINT32 ? "∞" : nm_sprintf_buf(buf, "%u", timeout_msec),
- v4 ? '4' : '6');
+ if (timeout_msec == G_MAXINT32) {
+ priv->ip_data_x[IS_IPv4].req_timeout_source = g_source_ref(nm_g_source_sentinel_get(0));
+ } else {
+ priv->ip_data_x[IS_IPv4].req_timeout_source = nm_g_timeout_add_source(
+ timeout_msec,
+ IS_IPv4 ? _dev_ip_state_req_timeout_cb_4 : _dev_ip_state_req_timeout_cb_6,
+ self);
+ }
+}
- if (timeout_msec == G_MAXINT32) {
- priv->ip_req_timeout_source_x[v4] = g_source_ref(nm_g_source_sentinel_get(0));
- } else {
- priv->ip_req_timeout_source_x[v4] =
- nm_g_timeout_add_source(timeout_msec,
- v4 ? ip_required_timeout_4 : ip_required_timeout_6,
- self);
+static gboolean
+_dev_ip_state_set_state(NMDevice * self,
+ int addr_family,
+ NMDeviceIPState ip_state,
+ const char * reason)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ int IS_IPv4;
+
+ if (addr_family == AF_UNSPEC) {
+ if (priv->ip_data.state == ip_state)
+ return FALSE;
+ _LOGD_ip(addr_family,
+ "set (combined) state %s (was %s, reason: %s)",
+ nm_device_ip_state_to_string(ip_state),
+ nm_device_ip_state_to_string(priv->ip_data.state),
+ reason);
+ priv->ip_data.state_ = ip_state;
+ return TRUE;
+ }
+
+ IS_IPv4 = NM_IS_IPv4(addr_family);
+
+ if (priv->ip_data_x[IS_IPv4].state_ == ip_state)
+ return FALSE;
+
+ _LOGD_ip(addr_family,
+ "set state %s (was %s, reason: %s)",
+ nm_device_ip_state_to_string(ip_state),
+ nm_device_ip_state_to_string(priv->ip_data_x[IS_IPv4].state),
+ reason);
+ priv->ip_data_x[IS_IPv4].state_ = ip_state;
+ return TRUE;
+}
+
+static void
+_device_ip_state_accumulate(NMDeviceIPState state,
+ gboolean * out_is_started,
+ gboolean * out_is_pending,
+ gboolean * out_is_failed)
+{
+ switch (state) {
+ case NM_DEVICE_IP_STATE_NONE:
+ return;
+ case NM_DEVICE_IP_STATE_PENDING:
+ *out_is_started = TRUE;
+ *out_is_pending = TRUE;
+ return;
+ case NM_DEVICE_IP_STATE_READY:
+ *out_is_started = TRUE;
+ return;
+ case NM_DEVICE_IP_STATE_FAILED:
+ *out_is_started = TRUE;
+ *out_is_failed = TRUE;
+ return;
+ }
+ nm_assert_not_reached();
+ return;
+}
+
+static void
+_dev_ip_state_check(NMDevice *self, int addr_family)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ gboolean s_is_started = FALSE;
+ gboolean s_is_failed = FALSE;
+ gboolean s_is_pending = FALSE;
+ gboolean v_bool;
+ NMDeviceIPState ip_state;
+ NMDeviceIPState ip_state_other;
+ NMDeviceIPState combinedip_state;
+ NMTernary may_fail = NM_TERNARY_DEFAULT;
+ NMTernary may_fail_other = NM_TERNARY_DEFAULT;
+
+ /* State handling in NMDevice:
+ *
+ * NMDevice manages a lot of state, that is for the various IP addressing methods, the state
+ * of the interface (controller/port), and a overall nm_device_get_state().
+ *
+ * The idea is to compartmentalize these states into smaller units, and combine them as appropriate.
+ *
+ * For example, NMDhcpClient already provides an API that hides most of the complexity. But it still
+ * needs to expose some state, like whether we are still trying to get a lease (PENDING), whether there
+ * was a critical failure (FAILED) or we have a lease (READY). This state is grouped in NMDevice
+ * under priv->ipdhcp_data_x. Most important is priv->ipdhcp_data_x[].state, which distills all of this
+ * into 4 values of type NMDeviceIPState. This state is cached, so whenever something changes (e.g.
+ * an event from NMDhcpClient), we determine the new state and compare it with what is cached. If
+ * the cached state is as the new state, we are done. Otherwise, the change gets escalated (which
+ * means to call _dev_ip_state_check_async()).
+ *
+ * Then, the various sub-states escalate their changes to this function (_dev_ip_state_check). This
+ * function first takes the sub-states related to one IP address family, and combines them into
+ * priv->ip_data_x[] (and in particular priv->ip_data_x[].state). The same repeats. The current
+ * state is cached in priv->ip_data_x[].state, and _dev_ip_state_check() determines the new state.
+ * If there is no change, it ends here. Otherwise, it gets escalated. In this case, the escaplation
+ * happens in _dev_ip_state_check() below by combining the combined per-address-family into
+ * priv->ip_data. In particular this step needs to take into account settings like "may-fail"
+ * and "required-timeout".
+ *
+ * The escalation and compartmentalization priv->ip_data repeats. This time it escalates
+ * to the overall device state (nm_device_state_changed() and nm_device_get_state()), which then
+ * triggers larger state changes (e.g. the activation might fail).
+ */
+
+ if (priv->l3cfg && nm_l3cfg_commit_on_idle_is_scheduled(priv->l3cfg)) {
+ /* we have an update on NML3Cfg scheduled. We first process that, before
+ * progressing the IP state. When that's done, we will be called again. */
+ _dev_ip_state_check_async(self, addr_family);
+ return;
+ }
+
+ if (priv->ip_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_NONE) {
+ ip_state = NM_DEVICE_IP_STATE_NONE;
+ goto got_ip_state;
+ }
+
+ if (nm_device_sys_iface_state_is_external(self)) {
+ ip_state = NM_DEVICE_IP_STATE_READY;
+ goto got_ip_state;
+ }
+
+ if (priv->ip_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_PENDING
+ && (priv->state < NM_DEVICE_STATE_IP_CONFIG || priv->state > NM_DEVICE_STATE_ACTIVATED)) {
+ /* we can only leave pending state, if we are between (including) IP_CONFIG and ACTIVATED states. */
+ ip_state = NM_DEVICE_IP_STATE_PENDING;
+ goto got_ip_state;
+ }
+
+ if (priv->ip_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_PENDING
+ && nm_active_connection_get_master(NM_ACTIVE_CONNECTION(priv->act_request.obj))
+ && !priv->is_enslaved) {
+ /* Don't progress into IP_CHECK or SECONDARIES if we're waiting for the
+ * master to enslave us. */
+ ip_state = NM_DEVICE_IP_STATE_PENDING;
+ goto got_ip_state;
+ }
+
+ if (priv->ip_data_x[IS_IPv4].wait_for_carrier || priv->ip_data_x[IS_IPv4].wait_for_ports) {
+ ip_state = NM_DEVICE_IP_STATE_PENDING;
+ goto got_ip_state;
+ }
+
+ if (priv->ip_data_x[IS_IPv4].is_disabled || priv->ip_data_x[IS_IPv4].is_ignore) {
+ ip_state = NM_DEVICE_IP_STATE_READY;
+ goto got_ip_state;
+ }
+
+ _device_ip_state_accumulate(priv->ipmanual_data.state,
+ &s_is_started,
+ &s_is_pending,
+ &s_is_failed);
+
+ _device_ip_state_accumulate(priv->ipll_data_x[IS_IPv4].state,
+ &s_is_started,
+ &s_is_pending,
+ &s_is_failed);
+
+ if (!IS_IPv4) {
+ _device_ip_state_accumulate(priv->ipac6_data.state,
+ &s_is_started,
+ &s_is_pending,
+ &s_is_failed);
+ }
+
+ v_bool = FALSE;
+ _device_ip_state_accumulate(priv->ipdhcp_data_x[IS_IPv4].state,
+ &s_is_started,
+ &s_is_pending,
+ &v_bool);
+ if (v_bool) {
+ if (!IS_IPv4 && priv->ipdhcp_data_6.v6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) {
+ /* DHCPv6 is best-effort and not required. */
+ } else
+ s_is_failed = TRUE;
+ }
+
+ _device_ip_state_accumulate(priv->ipdev_data_x[IS_IPv4].state,
+ &s_is_started,
+ &s_is_pending,
+ &s_is_failed);
+
+ _device_ip_state_accumulate(priv->ipdev_data_unspec.state,
+ &s_is_started,
+ &s_is_pending,
+ &s_is_failed);
+
+ if (s_is_failed)
+ ip_state = NM_DEVICE_IP_STATE_FAILED;
+ else if (s_is_pending)
+ ip_state = NM_DEVICE_IP_STATE_PENDING;
+ else if (s_is_started)
+ ip_state = NM_DEVICE_IP_STATE_READY;
+ else
+ ip_state = NM_DEVICE_IP_STATE_PENDING;
+
+got_ip_state:
+
+#define _state_str_a(state, name) \
+ ({ \
+ const NMDeviceIPState _state = (state); \
+ char * _s = ""; \
+ \
+ if (_state != NM_DEVICE_IP_STATE_NONE) { \
+ _s = nm_sprintf_bufa(NM_STRLEN(name) + 11, \
+ " " name "=%s", \
+ nm_device_ip_state_to_string(_state)); \
+ } \
+ _s; \
+ })
+
+ nm_assert(!priv->ip_data_4.is_ignore);
+
+ _LOGT_ip(addr_family,
+ "check-state: state %s => %s, is_failed=%d, is_pending=%d, is_started=%d, "
+ "may-fail-4=%d, may-fail-6=%d;"
+ "%s;%s%s%s%s%s;%s%s%s%s%s%s%s",
+ nm_device_ip_state_to_string(priv->ip_data_x[IS_IPv4].state),
+ nm_device_ip_state_to_string(ip_state),
+ s_is_failed,
+ s_is_pending,
+ s_is_started,
+ _prop_get_ipvx_may_fail_cached(self, AF_INET, IS_IPv4 ? &may_fail : &may_fail_other),
+ _prop_get_ipvx_may_fail_cached(self, AF_INET6, !IS_IPv4 ? &may_fail : &may_fail_other),
+ _state_str_a(priv->ipmanual_data.state, "manualip"),
+ priv->ip_data_4.is_disabled ? " disabled4" : "",
+ _state_str_a(priv->ipll_data_4.state, "ll4"),
+ _state_str_a(priv->ipdhcp_data_4.state, "dhcp4"),
+ _state_str_a(priv->ipdev_data_4.state, "dev4"),
+ _state_str_a(priv->ipshared_data_4.state, "shared4"),
+ priv->ip_data_6.is_disabled ? " disabled6" : "",
+ priv->ip_data_6.is_ignore ? " ignore6" : "",
+ _state_str_a(priv->ipll_data_6.state, "ll6"),
+ _state_str_a(priv->ipac6_data.state, "ac6"),
+ _state_str_a(priv->ipdhcp_data_6.state, "dhcp6"),
+ _state_str_a(priv->ipdev_data_6.state, "dev6"),
+ _state_str_a(priv->ipshared_data_6.state, "shared6"));
+
+ if (priv->ip_data_x[IS_IPv4].state == ip_state) {
+ /* no change. We can stop here. However, we also cancel the pending check, if any,
+ * because we just determined that there is no change. */
+ } else {
+ _dev_ip_state_set_state(self, addr_family, ip_state, "check-ip-state");
+ }
+
+ if (ip_state == NM_DEVICE_IP_STATE_NONE) {
+ /* Nothing to do. This almost cannot happen, and there is probably nothing
+ * to do about this case. */
+ goto out_done;
+ }
+
+ ip_state_other = priv->ip_data_x[!IS_IPv4].state;
+
+ if (ip_state == NM_DEVICE_IP_STATE_READY) {
+ /* we only set NM_ACTIVATION_STATE_FLAG_IP_READY_X() flag once we reach NM_DEVICE_IP_STATE_READY state.
+ * We don't ever clear it, even if we later enter NM_DEVICE_IP_STATE_FAILED state.
+ *
+ * This is not documented/guaranteed behavior, but seems to make sense for now. */
+ _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_IP_READY_X(IS_IPv4));
+ }
+
+ if (ip_state == NM_DEVICE_IP_STATE_READY && ip_state_other == NM_DEVICE_IP_STATE_READY)
+ combinedip_state = NM_DEVICE_IP_STATE_READY;
+ else if (ip_state == NM_DEVICE_IP_STATE_READY && ip_state_other == NM_DEVICE_IP_STATE_PENDING
+ && (priv->ip_data_x[IS_IPv4].is_disabled || priv->ip_data_x[IS_IPv4].is_ignore)) {
+ /* This IP method is disabled/ignore, but the other family is still pending.
+ * Regardless of ipvx.may-fail, this means that we always require the other IP family
+ * to get ready too. */
+ combinedip_state = NM_DEVICE_IP_STATE_PENDING;
+ } else if (ip_state == NM_DEVICE_IP_STATE_READY && ip_state_other == NM_DEVICE_IP_STATE_PENDING
+ && (priv->ip_data_x[!IS_IPv4].req_timeout_source
+ || !_prop_get_ipvx_may_fail_cached(self,
+ nm_utils_addr_family_other(addr_family),
+ &may_fail_other)))
+ combinedip_state = NM_DEVICE_IP_STATE_PENDING;
+ else if (ip_state == NM_DEVICE_IP_STATE_READY && ip_state_other == NM_DEVICE_IP_STATE_PENDING
+ && _prop_get_ipvx_may_fail_cached(self,
+ nm_utils_addr_family_other(addr_family),
+ &may_fail_other))
+ combinedip_state = NM_DEVICE_IP_STATE_READY;
+ else if (ip_state == NM_DEVICE_IP_STATE_FAILED
+ && !_prop_get_ipvx_may_fail_cached(self, addr_family, &may_fail))
+ combinedip_state = NM_DEVICE_IP_STATE_FAILED;
+ else {
+ if (priv->ip_data.state == NM_DEVICE_IP_STATE_NONE)
+ combinedip_state = NM_DEVICE_IP_STATE_PENDING;
+ else
+ combinedip_state = priv->ip_data.state;
+ }
+
+ _LOGT_ip(AF_UNSPEC,
+ "check-state: (combined) state %s => %s",
+ nm_device_ip_state_to_string(priv->ip_data.state),
+ nm_device_ip_state_to_string(combinedip_state));
+
+ if (!_dev_ip_state_set_state(self, AF_UNSPEC, combinedip_state, "check-ip-state"))
+ goto out_done;
+
+ switch (combinedip_state) {
+ case NM_DEVICE_IP_STATE_PENDING:
+ break;
+ case NM_DEVICE_IP_STATE_READY:
+ _dev_ip_state_req_timeout_cancel(self, AF_UNSPEC);
+ if (priv->state == NM_DEVICE_STATE_IP_CONFIG) {
+ nm_device_state_changed(self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
+ }
+ break;
+ case NM_DEVICE_IP_STATE_FAILED:
+ nm_device_state_changed(self,
+ NM_DEVICE_STATE_FAILED,
+ NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ break;
+ case NM_DEVICE_IP_STATE_NONE:
+ default:
+ nm_assert_not_reached();
+ }
+
+out_done:
+ /* we just checked the state. We can cancel the pending async check. */
+ nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].check_async_source);
+}
+
+static gboolean
+_dev_ip_state_check_async_cb(NMDevice *self, int addr_family)
+{
+ _dev_ip_state_check(self, addr_family);
+ return G_SOURCE_CONTINUE;
+}
+
+static gboolean
+_dev_ip_state_check_async_cb_4(gpointer user_data)
+{
+ return _dev_ip_state_check_async_cb(user_data, AF_INET);
+}
+
+static gboolean
+_dev_ip_state_check_async_cb_6(gpointer user_data)
+{
+ return _dev_ip_state_check_async_cb(user_data, AF_INET6);
+}
+
+static void
+_dev_ip_state_check_async(NMDevice *self, int addr_family)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ int IS_IPv4;
+
+ if (addr_family == AF_UNSPEC) {
+ _dev_ip_state_check_async(self, AF_INET);
+ _dev_ip_state_check_async(self, AF_INET6);
+ return;
+ }
+
+ IS_IPv4 = NM_IS_IPv4(addr_family);
+ if (!priv->ip_data_x[IS_IPv4].check_async_source) {
+ priv->ip_data_x[IS_IPv4].check_async_source = nm_g_idle_add_source(
+ (IS_IPv4 ? _dev_ip_state_check_async_cb_4 : _dev_ip_state_check_async_cb_6),
+ self);
+ }
+}
+
+static void
+_dev_ip_state_cleanup(NMDevice *self, int addr_family)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ int IS_IPv4;
+
+ if (addr_family == AF_UNSPEC) {
+ _dev_ip_state_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE, "ip-state-clear");
+ return;
+ }
+
+ IS_IPv4 = NM_IS_IPv4(addr_family);
+
+ nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].check_async_source);
+ nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].req_timeout_source);
+ _dev_ip_state_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE, "ip-state-clear");
+ priv->ip_data_x[IS_IPv4].wait_for_carrier = FALSE;
+ priv->ip_data_x[IS_IPv4].wait_for_ports = FALSE;
+ priv->ip_data_x[IS_IPv4].is_disabled = FALSE;
+ priv->ip_data_x[IS_IPv4].is_ignore = FALSE;
+ priv->ip_data_x[IS_IPv4].do_reapply = FALSE;
+}
+
+/*****************************************************************************/
+
+static gpointer
+_dev_l3_config_data_tag_get(NMDevicePrivate *priv, L3ConfigDataType l3cd_type)
+{
+ nm_assert(_NM_INT_NOT_NEGATIVE(l3cd_type) && l3cd_type < G_N_ELEMENTS(priv->l3cds));
+
+ return &priv->l3cds[l3cd_type];
+}
+
+static L3ConfigDataType
+_dev_l3_config_data_tag_to_type(NMDevice *self, gconstpointer tag)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ int d;
+
+ /* In C it is undefined behavior to compare unrelated pointers.
+ * Work around that by using nm_ptr_to_uintptr(), which casts the pointers
+ * to integers.
+ *
+ * I guess, theoretically it's still a problem to assume that if tag pointers
+ * somewhere inside priv->l3cds, that the uintptr_t case would also yield
+ * a value in that range. In practice, I couldn't imaging this not not work
+ * reliably. */
+
+ if (nm_ptr_to_uintptr(tag) < nm_ptr_to_uintptr(&priv->l3cds[0])
+ || nm_ptr_to_uintptr(tag) >= nm_ptr_to_uintptr(&priv->l3cds[G_N_ELEMENTS(priv->l3cds)]))
+ return _L3_CONFIG_DATA_TYPE_NONE;
+
+ d = ((typeof(priv->l3cds[0]) *) tag) - (&priv->l3cds[0]);
+
+ nm_assert(d >= 0);
+ nm_assert(d < _L3_CONFIG_DATA_TYPE_NUM);
+ nm_assert(tag == &priv->l3cds[d]);
+ nm_assert(tag == _dev_l3_config_data_tag_get(priv, d));
+ return d;
+}
+
+static L3ConfigDataType
+_dev_l3_config_data_acd_addr_info_to_type(NMDevice * self,
+ const NML3AcdAddrInfo *addr_info,
+ guint i_track_infos)
+{
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert(addr_info);
+ nm_assert(i_track_infos < addr_info->n_track_infos);
+
+ return _dev_l3_config_data_tag_to_type(self, addr_info->track_infos[i_track_infos].tag);
+}
+
+// FIXME(l3cfg): unused function??
+_nm_unused static const NML3AcdAddrTrackInfo *
+_dev_l3_config_data_acd_addr_info_has_by_type(NMDevice * self,
+ const NML3AcdAddrInfo *addr_info,
+ L3ConfigDataType l3cd_type)
+{
+ guint i;
+
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert(addr_info);
+ nm_assert(_NM_INT_NOT_NEGATIVE(l3cd_type) && l3cd_type < _L3_CONFIG_DATA_TYPE_NUM);
+
+ for (i = 0; i < addr_info->n_track_infos; i++) {
+ if (l3cd_type == _dev_l3_config_data_acd_addr_info_to_type(self, addr_info, i))
+ return &addr_info->track_infos[i];
+ }
+ return NULL;
+}
+
+static void
+_dev_l3_get_config_settings(NMDevice * self,
+ L3ConfigDataType type,
+ NML3ConfigMergeFlags *out_merge_flags,
+ NML3AcdDefendType * out_acd_defend_type,
+ guint32 * out_acd_timeout_msec)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NML3ConfigMergeFlags flags;
+ NMConnection * connection;
+ NMSettingIPConfig * s_ip;
+
+ nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < _L3_CONFIG_DATA_TYPE_NUM);
+
+ if (G_UNLIKELY(!priv->l3config_merge_flags_has)) {
+ int IS_IPv4;
+
+ connection = nm_device_get_applied_connection(self);
+
+ for (IS_IPv4 = 0; IS_IPv4 < 2; IS_IPv4++) {
+ flags = NM_L3_CONFIG_MERGE_FLAGS_NONE;
+
+ if (connection
+ && (s_ip = nm_connection_get_setting_ip_config(connection,
+ IS_IPv4 ? AF_INET : AF_INET6))) {
+ if (nm_setting_ip_config_get_ignore_auto_routes(s_ip))
+ flags |= NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES;
+
+ if (nm_setting_ip_config_get_ignore_auto_dns(s_ip))
+ flags |= NM_L3_CONFIG_MERGE_FLAGS_NO_DNS;
+
+ if (nm_setting_ip_config_get_never_default(s_ip)
+ || nm_setting_ip_config_get_gateway(s_ip)) {
+ /* if the connection has an explicit gateway, we also ignore
+ * the default routes from other sources. */
+ flags |= NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES;
}
}
+
+ priv->l3config_merge_flags_x[IS_IPv4] = flags;
+ }
+ priv->l3config_merge_flags_has = TRUE;
+ }
+
+ switch (type) {
+ case L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC:
+ case L3_CONFIG_DATA_TYPE_MANUALIP:
+ case L3_CONFIG_DATA_TYPE_LL_4:
+ case L3_CONFIG_DATA_TYPE_LL_6:
+ case L3_CONFIG_DATA_TYPE_PD_6:
+ case L3_CONFIG_DATA_TYPE_SHARED_4:
+ case L3_CONFIG_DATA_TYPE_DEVIP_4:
+ case L3_CONFIG_DATA_TYPE_AC_6:
+ case L3_CONFIG_DATA_TYPE_DHCP_6:
+ case L3_CONFIG_DATA_TYPE_DEVIP_6:
+ *out_acd_timeout_msec = _prop_get_ipv4_dad_timeout(self);
+ goto after_acd_timeout;
+
+ case L3_CONFIG_DATA_TYPE_DHCP_4:
+ /* For DHCP, we perform ACD separately, because we want to decline the
+ * lease in case of a conflict. */
+ *out_acd_timeout_msec = 0;
+ goto after_acd_timeout;
+
+ case _L3_CONFIG_DATA_TYPE_NUM:
+ case _L3_CONFIG_DATA_TYPE_NONE:
+ case _L3_CONFIG_DATA_TYPE_ACD_ONLY:
+ break;
+ }
+ *out_acd_timeout_msec = nm_assert_unreachable_val(0);
+
+after_acd_timeout:
+ switch (type) {
+ case L3_CONFIG_DATA_TYPE_LL_4:
+ *out_acd_defend_type = NM_L3_ACD_DEFEND_TYPE_ONCE;
+ goto after_acd_defend_type;
+
+ case L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC:
+ case L3_CONFIG_DATA_TYPE_MANUALIP:
+ case L3_CONFIG_DATA_TYPE_LL_6:
+ case L3_CONFIG_DATA_TYPE_PD_6:
+ case L3_CONFIG_DATA_TYPE_SHARED_4:
+ case L3_CONFIG_DATA_TYPE_DHCP_4:
+ case L3_CONFIG_DATA_TYPE_DEVIP_4:
+ case L3_CONFIG_DATA_TYPE_AC_6:
+ case L3_CONFIG_DATA_TYPE_DHCP_6:
+ case L3_CONFIG_DATA_TYPE_DEVIP_6:
+ *out_acd_defend_type = NM_L3_ACD_DEFEND_TYPE_ALWAYS;
+ goto after_acd_defend_type;
+
+ case _L3_CONFIG_DATA_TYPE_NUM:
+ case _L3_CONFIG_DATA_TYPE_NONE:
+ case _L3_CONFIG_DATA_TYPE_ACD_ONLY:
+ break;
+ }
+ *out_acd_defend_type = nm_assert_unreachable_val(NM_L3_ACD_DEFEND_TYPE_ALWAYS);
+
+after_acd_defend_type:
+ switch (type) {
+ case L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC:
+ case L3_CONFIG_DATA_TYPE_MANUALIP:
+ case L3_CONFIG_DATA_TYPE_LL_4:
+ case L3_CONFIG_DATA_TYPE_LL_6:
+ case L3_CONFIG_DATA_TYPE_PD_6:
+ case L3_CONFIG_DATA_TYPE_SHARED_4:
+ *out_merge_flags = NM_L3_CONFIG_MERGE_FLAGS_NONE;
+ goto after_merge_flags;
+
+ case L3_CONFIG_DATA_TYPE_DHCP_4:
+ case L3_CONFIG_DATA_TYPE_DEVIP_4:
+ *out_merge_flags = priv->l3config_merge_flags_4;
+ goto after_merge_flags;
+
+ case L3_CONFIG_DATA_TYPE_AC_6:
+ case L3_CONFIG_DATA_TYPE_DHCP_6:
+ case L3_CONFIG_DATA_TYPE_DEVIP_6:
+ *out_merge_flags = priv->l3config_merge_flags_6;
+ goto after_merge_flags;
+
+ case _L3_CONFIG_DATA_TYPE_NUM:
+ case _L3_CONFIG_DATA_TYPE_NONE:
+ case _L3_CONFIG_DATA_TYPE_ACD_ONLY:
+ break;
+ }
+ *out_merge_flags = nm_assert_unreachable_val(NM_L3_CONFIG_MERGE_FLAGS_NONE);
+
+after_merge_flags:
+ return;
+}
+
+static gboolean
+_dev_l3_register_l3cds_add_config(NMDevice *self, L3ConfigDataType l3cd_type)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NML3ConfigMergeFlags merge_flags;
+ NML3AcdDefendType acd_defend_type;
+ guint32 acd_timeout_msec;
+
+ _dev_l3_get_config_settings(self, l3cd_type, &merge_flags, &acd_defend_type, &acd_timeout_msec);
+ return nm_l3cfg_add_config(priv->l3cfg,
+ _dev_l3_config_data_tag_get(priv, l3cd_type),
+ FALSE,
+ priv->l3cds[l3cd_type].d,
+ l3cd_type,
+ nm_device_get_route_table(self, AF_INET),
+ nm_device_get_route_table(self, AF_INET6),
+ nm_device_get_route_metric(self, AF_INET),
+ nm_device_get_route_metric(self, AF_INET6),
+ _dev_default_route_metric_penalty_get(self, AF_INET),
+ _dev_default_route_metric_penalty_get(self, AF_INET6),
+ _prop_get_ipvx_dns_priority(self, AF_INET),
+ _prop_get_ipvx_dns_priority(self, AF_INET6),
+ acd_defend_type,
+ acd_timeout_msec,
+ NM_L3CFG_CONFIG_FLAGS_NONE,
+ merge_flags);
+}
+
+static gboolean
+_dev_l3_register_l3cds_set_one(NMDevice * self,
+ L3ConfigDataType l3cd_type,
+ const NML3ConfigData *l3cd,
+ NMTernary commit_sync)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
+ gboolean changed = FALSE;
+
+ if (priv->l3cds[l3cd_type].d != l3cd) {
+ if (nm_l3_config_data_equal(priv->l3cds[l3cd_type].d, l3cd)) {
+ /* we would set to a different instance, but the same content!
+ * We keep the previous one and ignore the new @l3cd.
+ *
+ * Warning: this means, that after calling this function,
+ * priv->l3cds[l3cd_type].d still might point to a different
+ * (though semantically equal) l3cd instance. */
+ } else {
+ l3cd_old = g_steal_pointer(&priv->l3cds[l3cd_type].d);
+ if (l3cd)
+ priv->l3cds[l3cd_type].d = nm_l3_config_data_ref_and_seal(l3cd);
+ }
+ }
+
+ if (priv->l3cfg) {
+ if (priv->l3cds[l3cd_type].d) {
+ if (_dev_l3_register_l3cds_add_config(self, l3cd_type))
+ changed = TRUE;
+ }
+
+ if (l3cd_old) {
+ if (nm_l3cfg_remove_config(priv->l3cfg,
+ _dev_l3_config_data_tag_get(priv, l3cd_type),
+ l3cd_old))
+ changed = TRUE;
+ }
+ }
+
+ if (changed && commit_sync != NM_TERNARY_DEFAULT)
+ _dev_l3_cfg_commit(self, !!commit_sync);
+
+ return changed;
+}
+
+static gboolean
+_dev_l3_register_l3cds(NMDevice *self,
+ NML3Cfg * l3cfg,
+ gboolean do_add /* else remove */,
+ NMTernary do_commit)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ gboolean is_external;
+ gboolean changed;
+ int i;
+
+ if (!l3cfg)
+ return FALSE;
+
+ is_external = nm_device_sys_iface_state_is_external(self);
+
+ changed = FALSE;
+ for (i = 0; i < (int) G_N_ELEMENTS(priv->l3cds); i++) {
+ if (!priv->l3cds[i].d)
+ continue;
+ if (!do_add) {
+ if (nm_l3cfg_remove_config(l3cfg,
+ _dev_l3_config_data_tag_get(priv, i),
+ priv->l3cds[i].d))
+ changed = TRUE;
+ continue;
}
+ if (is_external)
+ continue;
+ if (_dev_l3_register_l3cds_add_config(self, i))
+ changed = TRUE;
}
- if (priv->ip_state_x[IS_IPv4] == new_state)
+ if (do_commit == NM_TERNARY_DEFAULT)
+ do_commit = changed;
+ if (do_commit)
+ _dev_l3_cfg_commit(self, TRUE);
+
+ return changed;
+}
+
+/*****************************************************************************/
+
+void
+nm_device_l3cfg_commit(NMDevice *self, NML3CfgCommitType commit_type, gboolean do_sync)
+{
+ NMDevicePrivate *priv;
+
+ g_return_if_fail(NM_IS_DEVICE(self));
+
+ priv = NM_DEVICE_GET_PRIVATE(self);
+
+ if (!priv->l3cfg)
return;
- _LOGT(LOGD_DEVICE,
- "ip%c-state: set to %d (%s)",
- nm_utils_addr_family_to_char(addr_family),
- (int) new_state,
- nm_device_ip_state_to_string(new_state));
+ if (!do_sync) {
+ nm_l3cfg_commit_on_idle_schedule(priv->l3cfg, commit_type);
+ return;
+ }
- priv->ip_state_x_[IS_IPv4] = new_state;
+ nm_l3cfg_commit(priv->l3cfg, commit_type);
+}
- if (new_state == NM_DEVICE_IP_STATE_DONE) {
- /* we only set the IPx_READY flag once we reach NM_DEVICE_IP_STATE_DONE state. We don't
- * ever clear it, even if we later enter NM_DEVICE_IP_STATE_FAIL state.
- *
- * This is not documented/guaranteed behavior, but seems to make sense for now. */
- _active_connection_set_state_flags(self,
- NM_IS_IPv4(addr_family)
- ? NM_ACTIVATION_STATE_FLAG_IP4_READY
- : NM_ACTIVATION_STATE_FLAG_IP6_READY);
+static void
+_dev_l3_cfg_commit(NMDevice *self, gboolean do_sync)
+{
+ nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_AUTO, do_sync);
+}
+
+static void
+_dev_l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
+ nm_assert(l3cfg == priv->l3cfg);
+
+ switch (notify_data->notify_type) {
+ case NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED:
+ if (notify_data->l3cd_changed.commited) {
+ g_signal_emit(self,
+ signals[L3CD_CHANGED],
+ 0,
+ notify_data->l3cd_changed.l3cd_old,
+ notify_data->l3cd_changed.l3cd_new);
+ }
+ return;
+ case NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT:
+ {
+ const NML3AcdAddrInfo *addr_info = &notify_data->acd_event.info;
+
+ if (addr_info->state > NM_L3_ACD_ADDR_STATE_PROBING)
+ _dev_ipmanual_check_ready(self);
+ return;
+ }
+ case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT:
+ _dev_ipmanual_check_ready(self);
+ return;
+ case NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT:
+ nm_assert(NM_IS_L3_IPV4LL(notify_data->ipv4ll_event.ipv4ll));
+ if (priv->ipll_data_4.v4.ipv4ll == notify_data->ipv4ll_event.ipv4ll)
+ _dev_ipll4_notify_event(self);
+ return;
+ case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE:
+ return;
+ case NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED:
+ /* we commit again. This way we try to configure the routes.*/
+ _dev_l3_cfg_commit(self, FALSE);
+ return;
+ case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE:
+ if (NM_FLAGS_ANY(notify_data->platform_change_on_idle.obj_type_flags,
+ nmp_object_type_to_flags(NMP_OBJECT_TYPE_LINK)))
+ _dev_unamanged_check_external_down(self, TRUE);
+ _dev_ipmanual_check_ready(self);
+ return;
+
+ case _NM_L3_CONFIG_NOTIFY_TYPE_NUM:
+ break;
}
+ nm_assert_not_reached();
+}
+
+static void
+_dev_l3_cfg_commit_type_reset(NMDevice *self)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NML3CfgCommitType commit_type;
+
+ if (!priv->l3cfg)
+ return;
+
+ switch (priv->sys_iface_state) {
+ case NM_DEVICE_SYS_IFACE_STATE_EXTERNAL:
+ case NM_DEVICE_SYS_IFACE_STATE_REMOVED:
+ commit_type = NM_L3_CFG_COMMIT_TYPE_NONE;
+ goto do_set;
+ case NM_DEVICE_SYS_IFACE_STATE_ASSUME:
+ commit_type = NM_L3_CFG_COMMIT_TYPE_ASSUME;
+ goto do_set;
+ case NM_DEVICE_SYS_IFACE_STATE_MANAGED:
+ commit_type = NM_L3_CFG_COMMIT_TYPE_UPDATE;
+ goto do_set;
+ }
+ nm_assert_not_reached();
+ return;
+
+do_set:
+ priv->l3cfg_commit_type =
+ nm_l3cfg_commit_type_register(priv->l3cfg, commit_type, priv->l3cfg_commit_type, "device");
}
/*****************************************************************************/
@@ -2947,11 +3786,18 @@ nm_device_get_iface(NMDevice *self)
static gboolean
_set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- int * p_ifindex;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ gs_unref_object NML3Cfg *l3cfg_old = NULL;
+ NML3CfgCommitTypeHandle *l3cfg_commit_type_old = NULL;
+ gboolean l3_changed;
+ int ip_ifindex_new;
+ int * p_ifindex;
+ gboolean l3cfg_was_reset = FALSE;
- if (ifindex < 0)
+ if (ifindex < 0) {
+ nm_assert_not_reached();
ifindex = 0;
+ }
p_ifindex = is_ip_ifindex ? &priv->ip_ifindex_ : &priv->ifindex_;
@@ -2960,13 +3806,74 @@ _set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex)
*p_ifindex = ifindex;
- _LOGD(LOGD_DEVICE, "ifindex: set %sifindex %d", is_ip_ifindex ? "ip-" : "", ifindex);
+ ip_ifindex_new = nm_device_get_ip_ifindex(self);
- if (!is_ip_ifindex)
- _notify(self, PROP_IFINDEX);
+ if (priv->l3cfg) {
+ if (ip_ifindex_new <= 0 || ip_ifindex_new != nm_l3cfg_get_ifindex(priv->l3cfg)) {
+ g_signal_handlers_disconnect_by_func(priv->l3cfg,
+ G_CALLBACK(_dev_l3_cfg_notify_cb),
+ self);
+ l3cfg_old = g_steal_pointer(&priv->l3cfg_);
+ l3cfg_commit_type_old = g_steal_pointer(&priv->l3cfg_commit_type);
+ l3cfg_was_reset = TRUE;
+ }
+ }
+ if (!priv->l3cfg && ip_ifindex_new > 0) {
+ priv->l3cfg_ = nm_netns_access_l3cfg(priv->netns, ip_ifindex_new);
+
+ g_signal_connect(priv->l3cfg,
+ NM_L3CFG_SIGNAL_NOTIFY,
+ G_CALLBACK(_dev_l3_cfg_notify_cb),
+ self);
+
+ _dev_l3_cfg_commit_type_reset(self);
+ l3cfg_was_reset = TRUE;
+ }
+
+ _LOGD(LOGD_DEVICE,
+ "ifindex: set %sifindex %d%s%s%s%s%s%s",
+ is_ip_ifindex ? "ip-" : "",
+ ifindex,
+ NM_PRINT_FMT_QUOTED(l3cfg_old && l3cfg_old != priv->l3cfg,
+ " (old-l3cfg: ",
+ nm_hash_obfuscated_ptr_str_a(l3cfg_old),
+ ")",
+ ""),
+ NM_PRINT_FMT_QUOTED(priv->l3cfg && l3cfg_old != priv->l3cfg,
+ " (l3cfg: ",
+ nm_hash_obfuscated_ptr_str_a(priv->l3cfg),
+ ")",
+ ""));
if (priv->manager)
nm_manager_emit_device_ifindex_changed(priv->manager, self);
+
+ if (!is_ip_ifindex)
+ _notify(self, PROP_IFINDEX);
+
+ if (l3cfg_was_reset) {
+ nm_ip_config_take_and_unexport_on_idle(g_steal_pointer(&priv->l3ipdata_4.ip_config));
+ nm_ip_config_take_and_unexport_on_idle(g_steal_pointer(&priv->l3ipdata_6.ip_config));
+ if (priv->l3cfg) {
+ priv->l3ipdata_4.ip_config = nm_ip_config_new(AF_INET, priv->l3cfg, FALSE);
+ priv->l3ipdata_6.ip_config = nm_ip_config_new(AF_INET6, priv->l3cfg, FALSE);
+ }
+ _notify(self, PROP_IP4_CONFIG);
+ _notify(self, PROP_IP6_CONFIG);
+ }
+
+ l3_changed = FALSE;
+ if (_dev_l3_register_l3cds(self, priv->l3cfg, TRUE, FALSE))
+ l3_changed = TRUE;
+ if (_dev_l3_register_l3cds(self, l3cfg_old, FALSE, FALSE))
+ l3_changed = TRUE;
+
+ if (l3_changed)
+ _dev_l3_cfg_commit(self, TRUE);
+
+ if (l3cfg_commit_type_old)
+ nm_l3cfg_commit_type_unregister(l3cfg_old, l3cfg_commit_type_old);
+
return TRUE;
}
@@ -3703,8 +4610,10 @@ nm_device_get_route_metric_default(NMDeviceType device_type)
return 11000;
}
-static gboolean
-default_route_metric_penalty_detect(NMDevice *self, int addr_family)
+/* FIXME(l3cfg): we currently never call this function. We need to react
+ * to changes and re-commit the IP configuration with updated penalty. */
+_nm_unused static gboolean
+_dev_default_route_metric_penalty_detect(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
@@ -3719,7 +4628,7 @@ default_route_metric_penalty_detect(NMDevice *self, int addr_family)
}
static guint32
-default_route_metric_penalty_get(NMDevice *self, int addr_family)
+_dev_default_route_metric_penalty_get(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -3787,28 +4696,23 @@ nm_device_get_route_table(NMDevice *self, int addr_family)
return route_table ?: (guint32) RT_TABLE_MAIN;
}
-static NMIPRouteTableSyncMode
+/* FIXME(l3cfg): need to properly handle the route-table sync mode and
+ * use it during commit. */
+_nm_unused static NMIPRouteTableSyncMode
_get_route_table_sync_mode_stateful(NMDevice *self, int addr_family)
{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMDedupMultiIter ipconf_iter;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
gboolean all_sync_now;
gboolean all_sync_eff;
all_sync_now = _prop_get_ipvx_route_table(self, addr_family) != 0u;
if (!all_sync_now) {
- const NMPlatformIPRoute *route;
+ const NML3ConfigData *l3cd = priv->l3cds[L3_CONFIG_DATA_TYPE_MANUALIP].d;
/* If there's a local route switch to all-sync in order
* to properly manage the local table */
- nm_ip_config_iter_ip_route_for_each (&ipconf_iter, priv->con_ip_config_x[IS_IPv4], &route) {
- if (nm_platform_route_type_uncoerce(route->type_coerced) == RTN_LOCAL) {
- all_sync_now = TRUE;
- break;
- }
- }
+ all_sync_now = l3cd && nm_l3_config_data_has_routes_with_type_local(l3cd, addr_family);
}
if (all_sync_now)
@@ -3840,18 +4744,20 @@ nm_device_get_best_default_route(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- switch (addr_family) {
- case AF_INET:
- return priv->ip_config_4 ? nm_ip4_config_best_default_route_get(priv->ip_config_4) : NULL;
- case AF_INET6:
- return priv->ip_config_6 ? nm_ip6_config_best_default_route_get(priv->ip_config_6) : NULL;
- case AF_UNSPEC:
- return (priv->ip_config_4 ? nm_ip4_config_best_default_route_get(priv->ip_config_4) : NULL)
- ?: (priv->ip_config_6 ? nm_ip6_config_best_default_route_get(priv->ip_config_6)
- : NULL);
- default:
- g_return_val_if_reached(NULL);
- }
+ if (!priv->l3cfg)
+ return NULL;
+
+ /* FIXME(l3cfg): this function returns the best default route that we
+ * *want* to configure. What is the meaning of that? Possibly the caller
+ * cares whether there *is* a default route configured, for which they
+ * should ask platform.
+ *
+ * Check callers why they call this. Quite possibly this whole notion of
+ * "has a default route" is wrong to being with, regardless whether we
+ * look at the desired or actual configuration. That is, because "has a default route"
+ * does not do justice to the complexity of routing (with policy routing,
+ * etc.). */
+ return nm_l3cfg_get_best_default_route(priv->l3cfg, addr_family, TRUE);
}
const char *
@@ -4406,14 +5312,8 @@ concheck_update_state(NMDevice * self,
_notify(self, IS_IPv4 ? PROP_IP4_CONNECTIVITY : PROP_IP6_CONNECTIVITY);
- if (priv->state == NM_DEVICE_STATE_ACTIVATED && !nm_device_sys_iface_state_is_external(self)) {
- if (nm_device_get_best_default_route(self, AF_INET)
- && !ip_config_merge_and_apply(self, AF_INET, TRUE))
- _LOGW(LOGD_IP4, "Failed to update IPv4 route metric");
- if (nm_device_get_best_default_route(self, AF_INET6)
- && !ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "Failed to update IPv6 route metric");
- }
+ if (priv->state == NM_DEVICE_STATE_ACTIVATED && !nm_device_sys_iface_state_is_external(self))
+ _dev_l3_register_l3cds(self, priv->l3cfg, TRUE, NM_TERNARY_DEFAULT);
}
static const char *
@@ -4748,16 +5648,14 @@ find_slave_info(NMDevice *self, NMDevice *slave)
static gboolean
nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *connection)
{
- NMDevicePrivate *priv;
- SlaveInfo * info;
- gboolean success = FALSE;
- gboolean configure;
+ SlaveInfo *info;
+ gboolean success = FALSE;
+ gboolean configure;
g_return_val_if_fail(self != NULL, FALSE);
g_return_val_if_fail(slave != NULL, FALSE);
g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->enslave_slave != NULL, FALSE);
- priv = NM_DEVICE_GET_PRIVATE(self);
info = find_slave_info(self, slave);
if (!info)
return FALSE;
@@ -4780,22 +5678,17 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co
*/
nm_device_update_hw_address(self);
+ /* Since slave devices don't have their own IP configuration,
+ * set the MTU here.
+ */
+ _commit_mtu(slave);
+
/* Restart IP configuration if we're waiting for slaves. Do this
* after updating the hardware address as IP config may need the
* new address.
*/
- if (success) {
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_WAIT)
- nm_device_activate_stage3_ip_start(self, AF_INET);
-
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_WAIT)
- nm_device_activate_stage3_ip_start(self, AF_INET6);
- }
-
- /* Since slave devices don't have their own IP configuration,
- * set the MTU here.
- */
- _commit_mtu(slave, NM_DEVICE_GET_PRIVATE(slave)->ip_config_4);
+ if (success)
+ nm_device_activate_schedule_stage3_ip_config(self, FALSE);
return success;
}
@@ -4882,6 +5775,8 @@ nm_device_master_release_one_slave(NMDevice * self,
NM_DEVICE_STATE_REASON_REMOVED);
}
+/*****************************************************************************/
+
/**
* can_unmanaged_external_down:
* @self: the device
@@ -4896,7 +5791,7 @@ can_unmanaged_external_down(NMDevice *self)
}
static NMUnmanFlagOp
-is_unmanaged_external_down(NMDevice *self, gboolean consider_can)
+_dev_unmanaged_is_external_down(NMDevice *self, gboolean consider_can)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -4913,7 +5808,7 @@ is_unmanaged_external_down(NMDevice *self, gboolean consider_can)
}
static void
-set_unmanaged_external_down(NMDevice *self, gboolean only_if_unmanaged)
+_dev_unamanged_check_external_down(NMDevice *self, gboolean only_if_unmanaged)
{
NMUnmanFlagOp ext_flags;
@@ -4925,7 +5820,7 @@ set_unmanaged_external_down(NMDevice *self, gboolean only_if_unmanaged)
return;
}
- ext_flags = is_unmanaged_external_down(self, FALSE);
+ ext_flags = _dev_unmanaged_is_external_down(self, FALSE);
if (ext_flags != NM_UNMAN_FLAG_OP_SET_UNMANAGED) {
/* Ensure the assume check is queued before any queued state changes
* from the transition to UNAVAILABLE.
@@ -4953,26 +5848,15 @@ nm_device_update_dynamic_ip_setup(NMDevice *self)
g_hash_table_remove_all(priv->ip6_saved_properties);
- if (priv->dhcp_data_4.client) {
- if (!nm_device_dhcp4_renew(self, FALSE)) {
- nm_device_state_changed(self,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_DHCP_FAILED);
- return;
- }
- }
- if (priv->dhcp_data_6.client) {
- if (!nm_device_dhcp6_renew(self, FALSE)) {
- nm_device_state_changed(self,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_DHCP_FAILED);
- return;
- }
- }
- if (priv->ndisc) {
+ if (priv->ipdhcp_data_4.state != NM_DEVICE_IP_STATE_NONE)
+ _dev_ipdhcpx_restart(self, AF_INET, FALSE);
+ if (priv->ipdhcp_data_6.state != NM_DEVICE_IP_STATE_NONE)
+ _dev_ipdhcpx_restart(self, AF_INET6, FALSE);
+
+ if (priv->ipac6_data.ndisc) {
/* FIXME: todo */
}
- if (priv->dnsmasq_manager) {
+ if (priv->ipshared_data_4.v4.dnsmasq_manager) {
/* FIXME: todo */
}
}
@@ -5007,10 +5891,7 @@ carrier_changed(NMDevice *self, gboolean carrier)
nm_device_update_dynamic_ip_setup(self);
/* If needed, also resume IP configuration that is
* waiting for carrier. */
- if (nm_device_activate_ip4_state_in_wait(self))
- nm_device_activate_stage3_ip_start(self, AF_INET);
- if (nm_device_activate_ip6_state_in_wait(self))
- nm_device_activate_stage3_ip_start(self, AF_INET6);
+ nm_device_activate_schedule_stage3_ip_config(self, FALSE);
return;
}
/* fall-through and change state of device */
@@ -5108,10 +5989,6 @@ nm_device_set_carrier(NMDevice *self, gboolean carrier)
nm_device_remove_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE);
_carrier_wait_check_queued_act_request(self);
}
-
- /* Send ARP announcements if did not yet and have carrier. */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && !priv->acd.announcing)
- nm_device_arp_announce(self);
} else {
if (priv->carrier_wait_id)
nm_device_add_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE);
@@ -5243,85 +6120,6 @@ device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice
}
static void
-ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gs_unref_array GArray *addresses = NULL;
- gs_unref_array GArray *dns_servers = NULL;
- gs_unref_array GArray * dns_domains = NULL;
- guint len;
- guint i;
- const NMDedupMultiHeadEntry *head_entry;
- NMDedupMultiIter ipconf_iter;
-
- if (nm_ndisc_get_node_type(ndisc) != NM_NDISC_NODE_TYPE_ROUTER)
- return;
-
- head_entry = nm_ip6_config_lookup_addresses(priv->ip_config_6);
- addresses =
- g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscAddress), head_entry ? head_entry->len : 0);
- nm_dedup_multi_iter_for_each (&ipconf_iter, head_entry) {
- const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS(ipconf_iter.current->obj);
- NMNDiscAddress * ndisc_addr;
- guint32 lifetime;
- guint32 preferred;
-
- if (IN6_IS_ADDR_UNSPECIFIED(&addr->address) || IN6_IS_ADDR_LINKLOCAL(&addr->address))
- continue;
-
- if (addr->n_ifa_flags & IFA_F_TENTATIVE || addr->n_ifa_flags & IFA_F_DADFAILED)
- continue;
-
- if (addr->plen != 64)
- continue;
-
- lifetime = nmp_utils_lifetime_get(addr->timestamp,
- addr->lifetime,
- addr->preferred,
- NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000,
- &preferred);
- if (!lifetime)
- continue;
-
- g_array_set_size(addresses, addresses->len + 1);
- ndisc_addr = &g_array_index(addresses, NMNDiscAddress, addresses->len - 1);
- ndisc_addr->address = addr->address;
- ndisc_addr->expiry_msec =
- _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, lifetime);
- ndisc_addr->expiry_preferred_msec =
- _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, preferred);
- }
-
- len = nm_ip6_config_get_num_nameservers(priv->ip_config_6);
- dns_servers = g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscDNSServer), len);
- g_array_set_size(dns_servers, len);
- for (i = 0; i < len; i++) {
- const struct in6_addr *nameserver = nm_ip6_config_get_nameserver(priv->ip_config_6, i);
- NMNDiscDNSServer * ndisc_nameserver;
-
- ndisc_nameserver = &g_array_index(dns_servers, NMNDiscDNSServer, i);
- ndisc_nameserver->address = *nameserver;
- ndisc_nameserver->expiry_msec =
- _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, NM_NDISC_ROUTER_LIFETIME);
- }
-
- len = nm_ip6_config_get_num_searches(priv->ip_config_6);
- dns_domains = g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscDNSDomain), len);
- g_array_set_size(dns_domains, len);
- for (i = 0; i < len; i++) {
- const char * search = nm_ip6_config_get_search(priv->ip_config_6, i);
- NMNDiscDNSDomain *ndisc_search;
-
- ndisc_search = &g_array_index(dns_domains, NMNDiscDNSDomain, i);
- ndisc_search->domain = (char *) search;
- ndisc_search->expiry_msec =
- _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, NM_NDISC_ROUTER_LIFETIME);
- }
-
- nm_ndisc_set_config(ndisc, addresses, dns_servers, dns_domains);
-}
-
-static void
device_update_interface_flags(NMDevice *self, const NMPlatformLink *plink)
{
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
@@ -5352,8 +6150,9 @@ device_update_interface_flags(NMDevice *self, const NMPlatformLink *plink)
}
static gboolean
-device_link_changed(NMDevice *self)
+device_link_changed(gpointer user_data)
{
+ NMDevice * self = user_data;
NMDeviceClass * klass = NM_DEVICE_GET_CLASS(self);
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
gboolean ip_ifname_changed = FALSE;
@@ -5438,8 +6237,8 @@ device_link_changed(NMDevice *self)
nm_device_emit_recheck_auto_activate(self);
}
- if (priv->ndisc && pllink->inet6_token.id) {
- if (nm_ndisc_set_iid(priv->ndisc, pllink->inet6_token))
+ if (priv->ipac6_data.ndisc && pllink->inet6_token.id) {
+ if (nm_ndisc_set_iid(priv->ipac6_data.ndisc, pllink->inet6_token))
_LOGD(LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
}
@@ -5486,23 +6285,14 @@ device_link_changed(NMDevice *self)
nm_device_set_unmanaged_by_flags(self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason);
}
- set_unmanaged_external_down(self, FALSE);
+ _dev_unamanged_check_external_down(self, FALSE);
device_recheck_slave_status(self, pllink);
if (priv->up && (!was_up || seen_down)) {
/* the link was down and just came up. That happens for example, while changing MTU.
* We must restore IP configuration. */
- if (NM_IN_SET(priv->ip_state_4, NM_DEVICE_IP_STATE_CONF, NM_DEVICE_IP_STATE_DONE)) {
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE))
- _LOGW(LOGD_IP4, "failed applying IP4 config after link comes up again");
- }
-
- priv->linklocal6_dad_counter = 0;
- if (NM_IN_SET(priv->ip_state_6, NM_DEVICE_IP_STATE_CONF, NM_DEVICE_IP_STATE_DONE)) {
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "failed applying IP6 config after link comes up again");
- }
+ _dev_l3_cfg_commit(self, TRUE);
}
if (update_unmanaged_specs)
@@ -5524,8 +6314,9 @@ device_link_changed(NMDevice *self)
}
static gboolean
-device_ip_link_changed(NMDevice *self)
+device_ip_link_changed(gpointer user_data)
{
+ NMDevice * self = user_data;
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
const NMPlatformLink *pllink;
const char * ip_iface;
@@ -5588,13 +6379,12 @@ link_changed_cb(NMPlatform * platform,
if (!(info->n_ifi_flags & IFF_UP))
priv->device_link_changed_down = TRUE;
if (!priv->device_link_changed_id) {
- priv->device_link_changed_id = g_idle_add((GSourceFunc) device_link_changed, self);
+ priv->device_link_changed_id = g_idle_add(device_link_changed, self);
_LOGD(LOGD_DEVICE, "queued link change for ifindex %d", ifindex);
}
} else if (ifindex == nm_device_get_ip_ifindex(self)) {
if (!priv->device_ip_link_changed_id) {
- priv->device_ip_link_changed_id =
- g_idle_add((GSourceFunc) device_ip_link_changed, self);
+ priv->device_ip_link_changed_id = g_idle_add(device_ip_link_changed, self);
_LOGD(LOGD_DEVICE, "queued link change for ip-ifindex %d", ifindex);
}
}
@@ -6045,8 +6835,6 @@ realize_start_setup(NMDevice * self,
g_return_if_fail(nm_device_get_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT));
g_return_if_fail(priv->ip_ifindex <= 0);
g_return_if_fail(priv->ip_iface == NULL);
- g_return_if_fail(!priv->queued_ip_config_id_4);
- g_return_if_fail(!priv->queued_ip_config_id_6);
_LOGD(LOGD_DEVICE,
"start setup of %s, kernel ifindex %d",
@@ -6093,9 +6881,6 @@ realize_start_setup(NMDevice * self,
if (priv->firmware_version)
_notify(self, PROP_FIRMWARE_VERSION);
- priv->ipv6ll_handle = (nm_platform_link_get_inet6_addr_gen_mode(platform, priv->ifindex)
- == NM_IN6_ADDR_GEN_MODE_NONE);
-
if (nm_platform_link_supports_sriov(platform, priv->ifindex))
capabilities |= NM_DEVICE_CAP_SRIOV;
}
@@ -6153,7 +6938,7 @@ realize_start_setup(NMDevice * self,
* or have IP addressing */
nm_device_set_unmanaged_flags(self,
NM_UNMANAGED_EXTERNAL_DOWN,
- is_unmanaged_external_down(self, TRUE));
+ _dev_unmanaged_is_external_down(self, TRUE));
/* Unmanaged the loopback device with an explicit NM_UNMANAGED_BY_TYPE flag.
* Later we might want to manage 'lo' too. Currently, that doesn't work because
@@ -6192,9 +6977,6 @@ nm_device_realize_finish(NMDevice *self, const NMPlatformLink *plink)
if (plink)
device_recheck_slave_status(self, plink);
- priv->update_ip_config_completed_v4 = FALSE;
- priv->update_ip_config_completed_v6 = FALSE;
-
priv->real = TRUE;
_notify(self, PROP_REAL);
@@ -6290,9 +7072,6 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error)
}
}
- nm_clear_g_source(&priv->queued_ip_config_id_4);
- nm_clear_g_source(&priv->queued_ip_config_id_6);
-
g_object_freeze_notify(G_OBJECT(self));
NM_DEVICE_GET_CLASS(self)->unrealize_notify(self);
@@ -6656,117 +7435,6 @@ nm_device_get_master(NMDevice *self)
return NULL;
}
-static gboolean
-get_ip_config_may_fail(NMDevice *self, int addr_family)
-{
- NMConnection * connection;
- NMSettingIPConfig *s_ip;
-
- connection = nm_device_get_applied_connection(self);
-
- s_ip = nm_connection_get_setting_ip_config(connection, addr_family);
-
- return !s_ip || nm_setting_ip_config_get_may_fail(s_ip);
-}
-
-/*
- * check_ip_state
- *
- * When @full_state_update is TRUE, transition the device from IP_CONFIG to the
- * next state according to the outcome of IPv4 and IPv6 configuration. @may_fail
- * indicates that we are called just after the initial configuration and thus
- * IPv4/IPv6 are allowed to fail if the ipvx.may-fail properties say so, because
- * the IP methods couldn't even be started.
- * If @full_state_update is FALSE, just check if the connection should be failed
- * due to the state of both ip families and the ipvx.may-fail settings.
- */
-static void
-check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- gboolean ip4_disabled = FALSE, ip6_disabled = FALSE;
- NMSettingIPConfig *s_ip4, *s_ip6;
- NMDeviceState state;
- int IS_IPv4;
-
- if (full_state_update && nm_device_get_state(self) != NM_DEVICE_STATE_IP_CONFIG)
- return;
-
- /* Don't progress into IP_CHECK or SECONDARIES if we're waiting for the
- * master to enslave us. */
- if (nm_active_connection_get_master(NM_ACTIVE_CONNECTION(priv->act_request.obj))
- && !priv->is_enslaved)
- return;
-
- s_ip4 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG);
- if (s_ip4
- && nm_streq0(nm_setting_ip_config_get_method(s_ip4), NM_SETTING_IP4_CONFIG_METHOD_DISABLED))
- ip4_disabled = TRUE;
-
- s_ip6 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP6_CONFIG);
- if (s_ip6
- && NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip6),
- NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
- NM_SETTING_IP6_CONFIG_METHOD_DISABLED))
- ip6_disabled = TRUE;
-
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE
- && priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) {
- /* Both method completed (or disabled), proceed with activation */
- nm_device_state_changed(self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
- return;
- }
-
- for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
- if (priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_CONF
- && priv->ip_req_timeout_source_x[IS_IPv4]) {
- return;
- }
- }
-
- if ((priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL
- || (ip4_disabled && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE))
- && (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL
- || (ip6_disabled && priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE))) {
- /* Either both methods failed, or only one failed and the other is
- * disabled */
- if (nm_device_sys_iface_state_is_external_or_assume(self)) {
- /* We have assumed configuration, but couldn't redo it. No problem,
- * move to check state. */
- _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_DONE);
- _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_DONE);
- state = NM_DEVICE_STATE_IP_CHECK;
- } else if (may_fail && get_ip_config_may_fail(self, AF_INET)
- && get_ip_config_may_fail(self, AF_INET6)) {
- /* Couldn't start either IPv6 and IPv4 autoconfiguration,
- * but both are allowed to fail. */
- state = NM_DEVICE_STATE_SECONDARIES;
- } else {
- /* Autoconfiguration attempted without success. */
- state = NM_DEVICE_STATE_FAILED;
- }
-
- if (full_state_update || state == NM_DEVICE_STATE_FAILED) {
- nm_device_state_changed(self, state, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- }
- return;
- }
-
- /* If a method is still pending but required, wait */
- if (priv->ip_state_4 != NM_DEVICE_IP_STATE_DONE && !get_ip_config_may_fail(self, AF_INET))
- return;
- if (priv->ip_state_6 != NM_DEVICE_IP_STATE_DONE && !get_ip_config_may_fail(self, AF_INET6))
- return;
-
- /* If at least a method has completed, proceed with activation */
- if ((priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && !ip4_disabled)
- || (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE && !ip6_disabled)) {
- if (full_state_update)
- nm_device_state_changed(self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE);
- return;
- }
-}
-
/**
* nm_device_slave_notify_enslave:
* @self: the slave device
@@ -6804,13 +7472,17 @@ nm_device_slave_notify_enslave(NMDevice *self, gboolean success)
}
}
- if (activating) {
- if (success)
- check_ip_state(self, FALSE, TRUE);
- else
- nm_device_queue_state(self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
- } else
+ if (!activating) {
nm_device_queue_recheck_assume(self);
+ return;
+ }
+
+ if (!success) {
+ nm_device_queue_state(self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
+ return;
+ }
+
+ nm_device_activate_schedule_stage3_ip_config(self, FALSE);
}
/**
@@ -6881,6 +7553,9 @@ nm_device_removed(NMDevice *self, gboolean unconfigure_ip_config)
g_return_if_fail(NM_IS_DEVICE(self));
+ _dev_ipdhcpx_cleanup(self, AF_INET, TRUE, FALSE);
+ _dev_ipdhcpx_cleanup(self, AF_INET6, TRUE, FALSE);
+
priv = NM_DEVICE_GET_PRIVATE(self);
if (priv->master) {
/* this is called when something externally messes with the slave or during shut-down.
@@ -6892,15 +7567,7 @@ nm_device_removed(NMDevice *self, gboolean unconfigure_ip_config)
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
}
- if (unconfigure_ip_config) {
- nm_device_set_ip_config(self, AF_INET, NULL, FALSE, NULL);
- nm_device_set_ip_config(self, AF_INET6, NULL, FALSE, NULL);
- } else {
- if (priv->dhcp_data_4.client)
- nm_dhcp_client_stop(priv->dhcp_data_4.client, FALSE);
- if (priv->dhcp_data_6.client)
- nm_dhcp_client_stop(priv->dhcp_data_6.client, FALSE);
- }
+ _dev_l3_register_l3cds(self, priv->l3cfg, FALSE, TRUE);
}
static gboolean
@@ -7158,22 +7825,36 @@ nm_device_can_auto_connect(NMDevice *self, NMSettingsConnection *sett_conn, char
static gboolean
device_has_config(NMDevice *self)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ const NMDedupMultiHeadEntry *head_entry;
+ const NMPlatformLink * pllink;
+ NMPLookup lookup;
+
+ pllink = nm_l3cfg_get_pllink(priv->l3cfg, TRUE);
+ if (!pllink)
+ return FALSE;
- /* Check for IP configuration. */
- if (priv->ip_config_4 && nm_ip4_config_get_num_addresses(priv->ip_config_4))
+ if (pllink->master > 0) {
+ /* Master-slave relationship is also a configuration */
return TRUE;
- if (priv->ip_config_6 && nm_ip6_config_get_num_addresses(priv->ip_config_6))
+ }
+
+ head_entry = nm_platform_lookup(
+ nm_device_get_platform(self),
+ nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, pllink->ifindex));
+ if (head_entry)
return TRUE;
- /* The existence of a software device is good enough. */
- if (nm_device_is_software(self) && nm_device_is_real(self))
+ head_entry = nm_platform_lookup(
+ nm_device_get_platform(self),
+ nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, pllink->ifindex));
+ if (head_entry)
return TRUE;
- /* Master-slave relationship is also a configuration */
- if (!c_list_is_empty(&priv->slaves)
- || nm_platform_link_get_master(nm_device_get_platform(self), priv->ifindex) > 0)
+ if (nm_device_is_software(self) && nm_device_is_real(self)) {
+ /* The existence of a software device is good enough. */
return TRUE;
+ }
return FALSE;
}
@@ -7331,10 +8012,16 @@ nm_device_generate_connection(NMDevice *self,
}
} else {
/* Only regular and master devices get IP configuration; slaves do not */
- s_ip4 = nm_ip4_config_create_setting(priv->ip_config_4);
+ s_ip4 = nm_utils_platform_capture_ip_setting(nm_device_get_platform(self),
+ AF_INET,
+ nm_device_get_ip_ifindex(self),
+ FALSE);
nm_connection_add_setting(connection, s_ip4);
- s_ip6 = nm_ip6_config_create_setting(priv->ip_config_6, _get_maybe_ipv6_disabled(self));
+ s_ip6 = nm_utils_platform_capture_ip_setting(nm_device_get_platform(self),
+ AF_INET6,
+ nm_device_get_ip_ifindex(self),
+ _get_maybe_ipv6_disabled(self));
nm_connection_add_setting(connection, s_ip6);
nm_connection_add_setting(connection, nm_setting_proxy_new());
@@ -7800,20 +8487,6 @@ nm_device_emit_recheck_auto_activate(NMDevice *self)
g_signal_emit(self, signals[RECHECK_AUTO_ACTIVATE], 0);
}
-static void
-dnsmasq_state_changed_cb(NMDnsMasqManager *manager, guint32 status, gpointer user_data)
-{
- NMDevice *self = NM_DEVICE(user_data);
-
- switch (status) {
- case NM_DNSMASQ_STATUS_DEAD:
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
- break;
- default:
- break;
- }
-}
-
void
nm_device_auth_request(NMDevice * self,
GDBusMethodInvocation * context,
@@ -7838,148 +8511,112 @@ nm_device_auth_request(NMDevice * self,
/*****************************************************************************/
static void
-activation_source_clear(NMDevice *self, int addr_family)
+activation_source_clear(NMDevice *self)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (priv->activation_source_id_x[IS_IPv4] != 0) {
+ if (nm_clear_g_source_inst(&priv->activation_idle_source)) {
_LOGD(LOGD_DEVICE,
- "activation-stage: clear %s,v%c (id %u)",
- _activation_func_to_string(priv->activation_source_func_x[IS_IPv4]),
- nm_utils_addr_family_to_char(addr_family),
- priv->activation_source_id_x[IS_IPv4]);
- nm_clear_g_source(&priv->activation_source_id_x[IS_IPv4]);
- priv->activation_source_func_x[IS_IPv4] = NULL;
+ "activation-stage: clear %s",
+ _activation_func_to_string(priv->activation_func));
+ priv->activation_func = NULL;
}
}
static gboolean
-activation_source_handle_cb(NMDevice *self, int addr_family)
+activation_source_handle_cb(gpointer user_data)
{
+ NMDevice * self = user_data;
NMDevicePrivate * priv;
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- ActivationHandleFunc activation_source_func;
- guint activation_source_id;
+ ActivationHandleFunc activation_func;
g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE);
priv = NM_DEVICE_GET_PRIVATE(self);
- activation_source_func = priv->activation_source_func_x[IS_IPv4];
- activation_source_id = priv->activation_source_id_x[IS_IPv4];
+ g_return_val_if_fail(priv->activation_idle_source, G_SOURCE_REMOVE);
- g_return_val_if_fail(activation_source_id != 0, G_SOURCE_REMOVE);
- nm_assert(activation_source_func);
+ nm_assert(priv->activation_func);
- priv->activation_source_func_x[IS_IPv4] = NULL;
- priv->activation_source_id_x[IS_IPv4] = 0;
+ activation_func = priv->activation_func;
+ priv->activation_func = NULL;
- _LOGD(LOGD_DEVICE,
- "activation-stage: invoke %s,v%c (id %u)",
- _activation_func_to_string(activation_source_func),
- nm_utils_addr_family_to_char(addr_family),
- activation_source_id);
+ nm_clear_g_source_inst(&priv->activation_idle_source);
- activation_source_func(self);
+ _LOGD(LOGD_DEVICE, "activation-stage: invoke %s", _activation_func_to_string(activation_func));
- _LOGT(LOGD_DEVICE,
- "activation-stage: complete %s,v%c (id %u)",
- _activation_func_to_string(activation_source_func),
- nm_utils_addr_family_to_char(addr_family),
- activation_source_id);
+ activation_func(self);
- return G_SOURCE_REMOVE;
-}
-
-static gboolean
-activation_source_handle_cb_4(gpointer user_data)
-{
- return activation_source_handle_cb(user_data, AF_INET);
-}
-
-static gboolean
-activation_source_handle_cb_6(gpointer user_data)
-{
- return activation_source_handle_cb(user_data, AF_INET6);
+ return G_SOURCE_CONTINUE;
}
static void
-activation_source_schedule(NMDevice *self, ActivationHandleFunc func, int addr_family)
+activation_source_schedule(NMDevice *self, ActivationHandleFunc func)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- guint new_id = 0;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (priv->activation_source_id_x[IS_IPv4] != 0
- && priv->activation_source_func_x[IS_IPv4] == func) {
+ if (priv->activation_idle_source && priv->activation_func == func) {
/* Scheduling the same stage multiple times is fine. */
_LOGT(LOGD_DEVICE,
- "activation-stage: already scheduled %s,v%c (id %u)",
- _activation_func_to_string(func),
- nm_utils_addr_family_to_char(addr_family),
- priv->activation_source_id_x[IS_IPv4]);
+ "activation-stage: already scheduled %s",
+ _activation_func_to_string(func));
return;
}
- new_id =
- g_idle_add(IS_IPv4 ? activation_source_handle_cb_4 : activation_source_handle_cb_6, self);
-
- if (priv->activation_source_id_x[IS_IPv4] != 0) {
+ if (priv->activation_idle_source) {
_LOGD(LOGD_DEVICE,
- "activation-stage: schedule %s,v%c which replaces %s,v%c (id %u -> %u)",
+ "activation-stage: schedule %s (which replaces %s)",
_activation_func_to_string(func),
- nm_utils_addr_family_to_char(addr_family),
- _activation_func_to_string(priv->activation_source_func_x[IS_IPv4]),
- nm_utils_addr_family_to_char(addr_family),
- priv->activation_source_id_x[IS_IPv4],
- new_id);
- nm_clear_g_source(&priv->activation_source_id_x[IS_IPv4]);
+ _activation_func_to_string(priv->activation_func));
+ nm_clear_g_source_inst(&priv->activation_idle_source);
} else {
- _LOGD(LOGD_DEVICE,
- "activation-stage: schedule %s,v%c (id %u)",
- _activation_func_to_string(func),
- nm_utils_addr_family_to_char(addr_family),
- new_id);
+ _LOGD(LOGD_DEVICE, "activation-stage: schedule %s", _activation_func_to_string(func));
}
- priv->activation_source_func_x[IS_IPv4] = func;
- priv->activation_source_id_x[IS_IPv4] = new_id;
+ priv->activation_idle_source = nm_g_idle_add_source(activation_source_handle_cb, self);
+ priv->activation_func = func;
}
static void
-activation_source_invoke_sync(NMDevice *self, ActivationHandleFunc func, int addr_family)
+activation_source_invoke_sync(NMDevice *self, ActivationHandleFunc func)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (priv->activation_source_id_x[IS_IPv4] == 0) {
+ if (!priv->activation_idle_source) {
_LOGD(LOGD_DEVICE,
- "activation-stage: synchronously invoke %s,v%c",
- _activation_func_to_string(func),
- nm_utils_addr_family_to_char(addr_family));
- } else if (priv->activation_source_func_x[IS_IPv4] == func) {
+ "activation-stage: synchronously invoke %s",
+ _activation_func_to_string(func));
+ } else if (priv->activation_func == func) {
_LOGD(LOGD_DEVICE,
- "activation-stage: synchronously invoke %s,v%c which was already scheduled (id %u)",
- _activation_func_to_string(func),
- nm_utils_addr_family_to_char(addr_family),
- priv->activation_source_id_x[IS_IPv4]);
+ "activation-stage: synchronously invoke %s (which was already scheduled)",
+ _activation_func_to_string(func));
} else {
_LOGD(LOGD_DEVICE,
- "activation-stage: synchronously invoke %s,v%c which replaces %s,v%c (id %u)",
+ "activation-stage: synchronously invoke %s (which replaces %s)",
_activation_func_to_string(func),
- nm_utils_addr_family_to_char(addr_family),
- _activation_func_to_string(priv->activation_source_func_x[IS_IPv4]),
- nm_utils_addr_family_to_char(addr_family),
- priv->activation_source_id_x[IS_IPv4]);
+ _activation_func_to_string(priv->activation_func));
}
- nm_clear_g_source(&priv->activation_source_id_x[IS_IPv4]);
- priv->activation_source_func_x[IS_IPv4] = NULL;
+ nm_clear_g_source_inst(&priv->activation_idle_source);
+ priv->activation_func = NULL;
func(self);
}
+static void
+activation_source_invoke_or_schedule(NMDevice *self, ActivationHandleFunc func, gboolean do_sync)
+{
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert(NM_DEVICE_GET_PRIVATE(self)->act_request.obj);
+ nm_assert(func);
+
+ if (do_sync) {
+ activation_source_invoke_sync(self, func);
+ return;
+ }
+ activation_source_schedule(self, func);
+}
+
/*****************************************************************************/
static void
@@ -8148,14 +8785,20 @@ activate_stage1_device_prepare(NMDevice *self)
NMActiveConnection *master;
NMDeviceClass * klass;
- priv->v4_route_table_initialized = FALSE;
- priv->v6_route_table_initialized = FALSE;
+ nm_assert((priv->ip_data_4.state == NM_DEVICE_IP_STATE_NONE)
+ == (priv->ip_data_6.state == NM_DEVICE_IP_STATE_NONE));
- _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_NONE);
- _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_NONE);
+ if (priv->ip_data_4.state == NM_DEVICE_IP_STATE_NONE) {
+ _dev_ip_state_set_state(self, AF_INET, NM_DEVICE_IP_STATE_PENDING, "stage1");
+ _dev_ip_state_set_state(self, AF_INET6, NM_DEVICE_IP_STATE_PENDING, "stage1");
- /* Notify the new ActiveConnection along with the state change */
- nm_dbus_track_obj_path_set(&priv->act_request, priv->act_request.obj, TRUE);
+ /* Notify the new ActiveConnection along with the state change */
+ nm_dbus_track_obj_path_set(&priv->act_request, priv->act_request.obj, TRUE);
+
+ priv->v4_route_table_initialized = FALSE;
+ priv->v6_route_table_initialized = FALSE;
+ priv->l3config_merge_flags_has = FALSE;
+ }
nm_device_state_changed(self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
@@ -8216,6 +8859,7 @@ activate_stage1_device_prepare(NMDevice *self)
priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_PENDING;
return;
}
+
priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_COMPLETED;
}
@@ -8291,15 +8935,7 @@ activate_stage1_device_prepare(NMDevice *self)
void
nm_device_activate_schedule_stage1_device_prepare(NMDevice *self, gboolean do_sync)
{
- g_return_if_fail(NM_IS_DEVICE(self));
- g_return_if_fail(NM_DEVICE_GET_PRIVATE(self)->act_request.obj);
-
- if (!do_sync) {
- activation_source_schedule(self, activate_stage1_device_prepare, AF_INET);
- return;
- }
-
- activation_source_invoke_sync(self, activate_stage1_device_prepare, AF_INET);
+ activation_source_invoke_or_schedule(self, activate_stage1_device_prepare, do_sync);
}
static NMActStageReturn
@@ -8591,1084 +9227,732 @@ activate_stage2_device_config(NMDevice *self)
lldp_setup(self, NM_TERNARY_DEFAULT);
- _commit_mtu(self, NULL);
+ _commit_mtu(self);
- nm_device_activate_schedule_stage3_ip_config_start(self);
+ nm_device_activate_schedule_stage3_ip_config(self, TRUE);
}
void
nm_device_activate_schedule_stage2_device_config(NMDevice *self, gboolean do_sync)
{
- g_return_if_fail(NM_IS_DEVICE(self));
+ activation_source_invoke_or_schedule(self, activate_stage2_device_config, do_sync);
+}
- if (!do_sync) {
- activation_source_schedule(self, activate_stage2_device_config, AF_INET);
- return;
- }
+/*****************************************************************************/
- activation_source_invoke_sync(self, activate_stage2_device_config, AF_INET);
+static void
+_dev_ipllx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+
+ if (priv->ipll_data_x[IS_IPv4].state != state) {
+ _LOGD_ipll(addr_family,
+ "set state %s (was %s)",
+ nm_device_ip_state_to_string(state),
+ nm_device_ip_state_to_string(priv->ipll_data_x[IS_IPv4].state));
+ priv->ipll_data_x[IS_IPv4].state = state;
+ }
}
-void
-nm_device_ip_method_failed(NMDevice *self, int addr_family, NMDeviceStateReason reason)
+static void
+_dev_ipllx_cleanup(NMDevice *self, int addr_family)
{
- g_return_if_fail(NM_IS_DEVICE(self));
- g_return_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6));
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_FAIL);
+ if (IS_IPv4) {
+ if (nm_clear_pointer(&priv->ipll_data_4.v4.ipv4ll, nm_l3_ipv4ll_unref))
+ nm_clear_pointer(&priv->ipll_data_4.v4.ipv4ll_registation,
+ nm_l3_ipv4ll_register_remove);
+ else
+ nm_assert(!priv->ipll_data_4.v4.ipv4ll_registation);
- if (get_ip_config_may_fail(self, addr_family))
- check_ip_state(self, FALSE, (nm_device_get_state(self) == NM_DEVICE_STATE_IP_CONFIG));
- else
- nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, reason);
+ nm_clear_g_source_inst(&priv->ipll_data_4.v4.timeout_source);
+ } else {
+ nm_clear_pointer(&priv->ipll_data_6.v6.ipv6ll, nm_l3_ipv6ll_destroy);
+ priv->ipll_data_6.v6.llstate = NM_L3_IPV6LL_STATE_NONE;
+ priv->ipll_data_6.v6.lladdr = nm_ip_addr_zero.addr6;
+ nm_clear_g_source_inst(&priv->ipll_data_6.v6.retry_source);
+ }
+
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_LL_X(IS_IPv4), NULL, FALSE);
+
+ _dev_ipllx_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE);
}
/*****************************************************************************/
static void
-acd_data_destroy(gpointer ptr)
+_dev_ipll4_notify_event(NMDevice *self)
{
- AcdData *data = ptr;
- int i;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NML3IPv4LLState ipv4ll_state;
+ const NML3ConfigData *l3cd;
+ NMDeviceIPState state;
+
+ nm_assert(NM_IS_L3_IPV4LL(priv->ipll_data_4.v4.ipv4ll));
+ nm_assert(priv->ipll_data_4.state >= NM_DEVICE_IP_STATE_PENDING);
+
+ ipv4ll_state = nm_l3_ipv4ll_get_state(priv->ipll_data_4.v4.ipv4ll);
+
+ if (nm_l3_ipv4ll_state_is_good(ipv4ll_state)) {
+ l3cd = nm_l3_ipv4ll_get_l3cd(priv->ipll_data_4.v4.ipv4ll);
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
+ nm_assert(!nm_l3_ipv4ll_is_timed_out(priv->ipll_data_4.v4.ipv4ll));
+ state = NM_DEVICE_IP_STATE_READY;
+ } else if (priv->ipll_data_4.v4.ipv4ll
+ && nm_l3_ipv4ll_is_timed_out(priv->ipll_data_4.v4.ipv4ll)) {
+ l3cd = NULL;
+ state = NM_DEVICE_IP_STATE_FAILED;
+ } else {
+ l3cd = NULL;
+ state = (priv->ipll_data_4.state == NM_DEVICE_IP_STATE_PENDING) ? NM_DEVICE_IP_STATE_PENDING
+ : NM_DEVICE_IP_STATE_FAILED;
+ }
+
+ _dev_ipllx_set_state(self, AF_INET, state);
+
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_LL_4, l3cd, FALSE);
- for (i = 0; data->configs && data->configs[i]; i++)
- g_object_unref(data->configs[i]);
- g_free(data->configs);
- g_slice_free(AcdData, data);
+ _dev_ip_state_check_async(self, AF_INET);
}
static void
-ipv4_manual_method_apply(NMDevice *self, NMIP4Config **configs, gboolean success)
+_dev_ipll4_start(NMDevice *self)
{
- NMConnection *connection;
- const char * method;
-
- connection = nm_device_get_applied_connection(self);
- nm_assert(connection);
- method = nm_utils_get_ip_config_method(connection, AF_INET);
- nm_assert(NM_IN_STRSET(method,
- NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
- NM_SETTING_IP4_CONFIG_METHOD_AUTO));
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ guint32 timeout_msec;
- if (!success) {
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE);
+ if (priv->ipll_data_4.state >= NM_DEVICE_IP_STATE_PENDING)
return;
- }
- if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
- nm_device_activate_schedule_ip_config_result(self, AF_INET, NULL);
- else {
- if (NM_DEVICE_GET_PRIVATE(self)->ip_state_4 != NM_DEVICE_IP_STATE_DONE)
- ip_config_merge_and_apply(self, AF_INET, TRUE);
- }
+ _dev_ipllx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_PENDING);
+
+ timeout_msec = _prop_get_ipv4_dad_timeout(self);
+ if (timeout_msec == 0)
+ timeout_msec = NM_ACD_TIMEOUT_RFC5227_MSEC;
+
+ priv->ipll_data_4.v4.ipv4ll = nm_l3cfg_access_ipv4ll(priv->l3cfg);
+ priv->ipll_data_4.v4.ipv4ll_registation =
+ nm_l3_ipv4ll_register_new(priv->ipll_data_4.v4.ipv4ll, timeout_msec);
}
-static void
-acd_manager_probe_terminated(NMAcdManager *acd_manager, gpointer user_data)
+/*****************************************************************************/
+
+static const char *
+_device_get_dhcp_anycast_address(NMDevice *self)
{
- AcdData * data = user_data;
- NMDevice * self;
- NMDevicePrivate * priv;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *address;
- gboolean result, success = TRUE;
- int i;
+ NMDeviceClass *klass;
- g_assert(data);
- self = data->device;
- priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_assert(NM_IS_DEVICE(self));
- for (i = 0; data->configs && data->configs[i]; i++) {
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, data->configs[i], &address) {
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ klass = NM_DEVICE_GET_CLASS(self);
- result = nm_acd_manager_check_address(acd_manager, address->address);
- success &= result;
+ if (klass->get_dhcp_anycast_address)
+ return klass->get_dhcp_anycast_address(self);
- _NMLOG(result ? LOGL_DEBUG : LOGL_WARN,
- LOGD_DEVICE,
- "IPv4 DAD result: address %s is %s",
- _nm_utils_inet4_ntop(address->address, sbuf),
- result ? "unique" : "duplicate");
- }
- }
+ return NULL;
+}
- data->callback(self, data->configs, success);
+/*****************************************************************************/
- priv->acd.dad_list = g_slist_remove(priv->acd.dad_list, acd_manager);
- nm_acd_manager_free(acd_manager);
+static IPDevStateData *
+_dev_ipdev_data(NMDevice *self, int addr_family)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
+ switch (addr_family) {
+ case AF_INET:
+ return &priv->ipdev_data_4;
+ case AF_INET6:
+ return &priv->ipdev_data_6;
+ default:
+ nm_assert_not_reached();
+ /* fall-through */
+ case AF_UNSPEC:
+ return &priv->ipdev_data_unspec;
+ }
}
-/**
- * ipv4_dad_start:
- * @self: device instance
- * @configs: NULL-terminated array of IPv4 configurations
- * @cb: callback function
- *
- * Start IPv4 DAD on device @self, check addresses in @configs and call @cb
- * when the procedure ends. @cb will be called in any case, even if DAD can't
- * be started. @configs will be unreferenced after @cb has been called.
- */
static void
-ipv4_dad_start(NMDevice *self, NMIP4Config **configs, AcdCallback cb)
+_dev_ipdev_cleanup(NMDevice *self, int addr_family)
{
- static const NMAcdCallbacks acd_callbacks = {
- .probe_terminated_callback = acd_manager_probe_terminated,
- .user_data_destroy = acd_data_destroy,
- };
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMAcdManager * acd_manager;
- const NMPlatformIP4Address *address;
- NMDedupMultiIter ipconf_iter;
- AcdData * data;
- guint timeout;
- gboolean addr_found;
- int r;
- const guint8 * hwaddr_arr;
- size_t length;
- guint i;
+ IPDevStateData *p;
- g_return_if_fail(NM_IS_DEVICE(self));
- g_return_if_fail(configs);
- g_return_if_fail(cb);
-
- for (i = 0, addr_found = FALSE; configs[i]; i++) {
- if (nm_ip4_config_get_num_addresses(configs[i]) > 0) {
- addr_found = TRUE;
- break;
- }
+ p = _dev_ipdev_data(self, addr_family);
+ if (p->state != NM_DEVICE_IP_STATE_NONE) {
+ _LOGD_ipdev(addr_family, "reset state");
+ p->state = NM_DEVICE_IP_STATE_NONE;
+ p->failed_reason = NM_DEVICE_STATE_REASON_NONE;
}
+}
- timeout = _prop_get_ipv4_dad_timeout(self);
- hwaddr_arr = nm_platform_link_get_address(nm_device_get_platform(self),
- nm_device_get_ip_ifindex(self),
- &length);
+NMDeviceIPState
+nm_device_devip_get_state(NMDevice *self, int addr_family)
+{
+ g_return_val_if_fail(NM_IS_DEVICE(self), NM_DEVICE_IP_STATE_NONE);
- if (!timeout || !hwaddr_arr || !addr_found || length != ETH_ALEN
- || nm_device_sys_iface_state_is_external_or_assume(self)) {
- /* DAD not needed, signal success */
- cb(self, configs, TRUE);
+ return _dev_ipdev_data(self, addr_family)->state;
+}
- for (i = 0; configs[i]; i++)
- g_object_unref(configs[i]);
- g_free(configs);
+void
+nm_device_devip_set_state_full(NMDevice * self,
+ int addr_family,
+ NMDeviceIPState ip_state,
+ const NML3ConfigData *l3cd,
+ NMDeviceStateReason failed_reason)
+{
+ NMDevicePrivate *priv;
+ IPDevStateData * p;
- return;
- }
+ g_return_if_fail(NM_IS_DEVICE(self));
- data = g_slice_new0(AcdData);
- data->configs = configs;
- data->callback = cb;
- data->device = self;
+ priv = NM_DEVICE_GET_PRIVATE(self);
- acd_manager = nm_acd_manager_new(nm_device_get_ip_ifindex(self),
- hwaddr_arr,
- length,
- &acd_callbacks,
- data);
- priv->acd.dad_list = g_slist_append(priv->acd.dad_list, acd_manager);
+ nm_assert_addr_family_or_unspec(addr_family);
+ nm_assert(NM_IN_SET(ip_state,
+ NM_DEVICE_IP_STATE_PENDING,
+ NM_DEVICE_IP_STATE_READY,
+ NM_DEVICE_IP_STATE_FAILED));
+ nm_assert(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd));
- for (i = 0; configs[i]; i++) {
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, configs[i], &address)
- nm_acd_manager_add_address(acd_manager, address->address);
- }
+ nm_assert((ip_state != NM_DEVICE_IP_STATE_FAILED)
+ == (failed_reason == NM_DEVICE_STATE_REASON_NONE));
+ nm_assert((ip_state != NM_DEVICE_IP_STATE_FAILED) || !l3cd);
- r = nm_acd_manager_start_probe(acd_manager, timeout);
- if (r < 0) {
- _LOGW(LOGD_DEVICE, "acd probe failed");
+ p = _dev_ipdev_data(self, addr_family);
- /* DAD could not be started, signal success */
- cb(self, configs, TRUE);
+ if (p->state == ip_state && p->failed_reason == failed_reason
+ && priv->l3cds[L3_CONFIG_DATA_TYPE_DEVIP(addr_family)].d == l3cd)
+ return;
- priv->acd.dad_list = g_slist_remove(priv->acd.dad_list, acd_manager);
- nm_acd_manager_free(acd_manager);
+ if (ip_state == NM_DEVICE_IP_STATE_FAILED) {
+ _LOGD_ipdev(addr_family,
+ "set state=failed (reason %s)",
+ nm_device_state_reason_to_string_a(failed_reason));
+ } else {
+ _LOGD_ipdev(addr_family,
+ "set state=%s%s",
+ nm_device_ip_state_to_string(ip_state),
+ l3cd ? " (has extra IP configuration)" : "");
}
+ p->state = ip_state;
+ p->failed_reason = failed_reason;
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DEVIP(addr_family), l3cd, FALSE);
+ _dev_ip_state_check_async(self, addr_family);
}
/*****************************************************************************/
-/* IPv4LL stuff */
static void
-ipv4ll_cleanup(NMDevice *self)
+_dev_ipmanual_set_state(NMDevice *self, NMDeviceIPState state)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (priv->ipv4ll) {
- sd_ipv4ll_set_callback(priv->ipv4ll, NULL, NULL);
- sd_ipv4ll_stop(priv->ipv4ll);
- priv->ipv4ll = sd_ipv4ll_unref(priv->ipv4ll);
+ if (priv->ipmanual_data.state != state) {
+ _LOGD_ipmanual("set state %s", nm_device_ip_state_to_string(state));
+ priv->ipmanual_data.state = state;
}
-
- nm_clear_g_source(&priv->ipv4ll_timeout);
}
-static NMIP4Config *
-ipv4ll_get_ip4_config(NMDevice *self, guint32 lla)
+static void
+_dev_ipmanual_cleanup(NMDevice *self)
{
- NMIP4Config * config = NULL;
- NMPlatformIP4Address address;
- NMPlatformIP4Route route;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- config = nm_device_ip4_config_new(self);
- g_assert(config);
+ if (priv->ipmanual_data.state == NM_DEVICE_IP_STATE_NONE) {
+ nm_assert(!priv->l3cds[L3_CONFIG_DATA_TYPE_MANUALIP].d);
+ return;
+ }
- memset(&address, 0, sizeof(address));
- nm_platform_ip4_address_set_addr(&address, lla, 16);
- address.addr_source = NM_IP_CONFIG_SOURCE_IP4LL;
- nm_ip4_config_add_address(config, &address);
+ _dev_ipmanual_set_state(self, NM_DEVICE_IP_STATE_NONE);
- /* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */
- memset(&route, 0, sizeof(route));
- route.network = htonl(0xE0000000L);
- route.plen = 4;
- route.rt_source = NM_IP_CONFIG_SOURCE_IP4LL;
- route.table_coerced = nm_platform_route_table_coerce(nm_device_get_route_table(self, AF_INET));
- route.metric = nm_device_get_route_metric(self, AF_INET);
- nm_ip4_config_add_route(config, &route, NULL);
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_MANUALIP, NULL, FALSE);
- return config;
+ _dev_ip_state_check_async(self, AF_INET);
+ _dev_ip_state_check_async(self, AF_INET6);
}
static void
-nm_device_handle_ipv4ll_event(sd_ipv4ll *ll, int event, void *data)
+_dev_ipmanual_check_ready(NMDevice *self)
{
- NMDevice * self = data;
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- struct in_addr address;
- NMIP4Config * config;
- int r;
- if (priv->act_request.obj == NULL)
+ if (priv->ipmanual_data.state != NM_DEVICE_IP_STATE_PENDING) {
+ /* we only care about PENDING to get it READY. Currently not other
+ * conditions are implemented. That is, we cannot get to FAILED
+ * (maybe we should, if DAD fails) and we cannot get from anything
+ * once we are READY. */
return;
+ }
- nm_assert(nm_streq(nm_device_get_effective_ip_config_method(self, AF_INET),
- NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL));
+ if (!nm_l3cfg_check_ready(priv->l3cfg,
+ priv->l3cds[L3_CONFIG_DATA_TYPE_MANUALIP].d,
+ NM_L3CFG_CHECK_READY_FLAGS_IP4_ACD_READY
+ | NM_L3CFG_CHECK_READY_FLAGS_IP6_DAD_READY))
+ return;
- switch (event) {
- case SD_IPV4LL_EVENT_BIND:
- r = sd_ipv4ll_get_address(ll, &address);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r);
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED);
- return;
- }
+ _dev_ipmanual_set_state(self, NM_DEVICE_IP_STATE_READY);
+ _dev_ip_state_check_async(self, AF_UNSPEC);
+}
- if (!nm_utils_ip4_address_is_link_local(address.s_addr)) {
- _LOGE(LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr);
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_ERROR);
- return;
- }
+static void
+_dev_ipmanual_start(NMDevice *self)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
- config = ipv4ll_get_ip4_config(self, address.s_addr);
- if (config == NULL) {
- _LOGE(LOGD_AUTOIP4, "failed to get IPv4LL config");
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
- return;
- }
+ if (priv->ipmanual_data.state != NM_DEVICE_IP_STATE_NONE)
+ return;
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF) {
- nm_clear_g_source(&priv->ipv4ll_timeout);
- nm_device_activate_schedule_ip_config_result(self, AF_INET, NM_IP_CONFIG_CAST(config));
- } else if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) {
- applied_config_init(&priv->dev_ip_config_4, config);
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) {
- _LOGE(LOGD_AUTOIP4, "failed to update IP4 config for autoip change.");
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
- }
- } else
- g_assert_not_reached();
+ l3cd = nm_device_create_l3_config_data_from_connection(self,
+ nm_device_get_applied_connection(self));
- g_object_unref(config);
- break;
- default:
- _LOGW(LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event);
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
+ if (!l3cd) {
+ _dev_ipmanual_cleanup(self);
+ return;
}
-}
-
-static gboolean
-ipv4ll_timeout_cb(gpointer user_data)
-{
- NMDevice * self = NM_DEVICE(user_data);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (priv->ipv4ll_timeout) {
- _LOGI(LOGD_AUTOIP4, "IPv4LL configuration timed out.");
- priv->ipv4ll_timeout = 0;
- ipv4ll_cleanup(self);
+ /* Initially we set the state to pending, because we (maybe) have to perform ACD first. */
+ _dev_ipmanual_set_state(self, NM_DEVICE_IP_STATE_PENDING);
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET);
- }
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_MANUALIP, l3cd, FALSE);
- return FALSE;
+ _dev_ip_state_check_async(self, AF_INET);
+ _dev_ip_state_check_async(self, AF_INET6);
}
-static NMActStageReturn
-ipv4ll_start(NMDevice *self)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- const struct ether_addr *addr;
- int ifindex, r;
- size_t addr_len;
+/*****************************************************************************/
- ipv4ll_cleanup(self);
+static void
+_dev_ipdhcpx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- r = sd_ipv4ll_new(&priv->ipv4ll);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: new() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
+ if (priv->ipdhcp_data_x[IS_IPv4].state != state) {
+ _LOGD_ipdhcp(addr_family,
+ "set state %s (was %s)",
+ nm_device_ip_state_to_string(state),
+ nm_device_ip_state_to_string(priv->ipdhcp_data_x[IS_IPv4].state));
+ priv->ipdhcp_data_x[IS_IPv4].state = state;
}
+}
- r = sd_ipv4ll_attach_event(priv->ipv4ll, NULL, 0);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: attach_event() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+static void
+_dev_ipdhcpx_cleanup(NMDevice *self, int addr_family, gboolean full_cleanup, gboolean release)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- ifindex = nm_device_get_ip_ifindex(self);
- addr = nm_platform_link_get_address(nm_device_get_platform(self), ifindex, &addr_len);
- if (!addr || addr_len != ETH_ALEN) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: can't retrieve hardware address");
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE);
- r = sd_ipv4ll_set_mac(priv->ipv4ll, addr);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: set_mac() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
+ if (full_cleanup && !IS_IPv4) {
+ priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_NONE;
+ priv->ipdhcp_data_6.v6.needed_prefixes = 0;
}
- r = sd_ipv4ll_set_ifindex(priv->ipv4ll, ifindex);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: set_ifindex() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ if (full_cleanup)
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), NULL, FALSE);
- r = sd_ipv4ll_set_callback(priv->ipv4ll, nm_device_handle_ipv4ll_event, self);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: set_callback() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
+ if (priv->ipdhcp_data_x[IS_IPv4].client) {
+ nm_clear_g_signal_handler(priv->ipdhcp_data_x[IS_IPv4].client,
+ &priv->ipdhcp_data_x[IS_IPv4].notify_sigid);
+ nm_dhcp_client_stop(priv->ipdhcp_data_x[IS_IPv4].client, release);
+ g_clear_object(&priv->ipdhcp_data_x[IS_IPv4].client);
}
- r = sd_ipv4ll_start(priv->ipv4ll);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: start() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ if (full_cleanup && priv->ipdhcp_data_x[IS_IPv4].config) {
+ gs_unref_object NMDhcpConfig *config =
+ g_steal_pointer(&priv->ipdhcp_data_x[IS_IPv4].config);
- _LOGI(LOGD_DEVICE | LOGD_AUTOIP4, "IPv4LL: started");
+ _notify(self, PROP_DHCPX_CONFIG(IS_IPv4));
+ nm_dbus_object_unexport_on_idle(g_steal_pointer(&config));
+ }
- /* Start a timeout to bound the address attempt */
- priv->ipv4ll_timeout = g_timeout_add_seconds(20, ipv4ll_timeout_cb, self);
- return NM_ACT_STAGE_RETURN_POSTPONE;
+ _dev_ip_state_check_async(self, addr_family);
}
-/*****************************************************************************/
-
static void
-ensure_con_ip_config(NMDevice *self, int addr_family)
+_dev_ipdhcpx_handle_fail(NMDevice *self, int addr_family, const char *reason)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMConnection * connection;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMIPConfig * con_ip_config;
- if (priv->con_ip_config_x[IS_IPv4])
+ if (priv->ipdhcp_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_FAILED)
return;
- connection = nm_device_get_applied_connection(self);
- if (!connection)
- return;
+ _LOGT_ipdhcp(addr_family, "DHCP failing: %s", reason ?: "unknown reason");
- con_ip_config = nm_device_ip_config_new(self, addr_family);
+ _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_FAILED);
- if (IS_IPv4) {
- nm_ip4_config_merge_setting(NM_IP4_CONFIG(con_ip_config),
- nm_connection_get_setting_ip4_config(connection),
- _prop_get_connection_mdns(self),
- _prop_get_connection_llmnr(self),
- nm_device_get_route_table(self, addr_family),
- nm_device_get_route_metric(self, addr_family));
- } else {
- nm_ip6_config_merge_setting(NM_IP6_CONFIG(con_ip_config),
- nm_connection_get_setting_ip6_config(connection),
- nm_device_get_route_table(self, addr_family),
- nm_device_get_route_metric(self, addr_family));
- }
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), NULL, FALSE);
- if (nm_device_sys_iface_state_is_external_or_assume(self)) {
- /* For assumed connections ignore all addresses and routes. */
- nm_ip_config_reset_addresses(con_ip_config);
- nm_ip_config_reset_routes(con_ip_config);
- }
+ if (priv->ipdhcp_data_x[IS_IPv4].config)
+ nm_dhcp_config_set_lease(priv->ipdhcp_data_x[IS_IPv4].config, NULL);
- priv->con_ip_config_x[IS_IPv4] = con_ip_config;
-}
-
-/*****************************************************************************/
-
-static const char *
-_device_get_dhcp_anycast_address(NMDevice *self)
-{
- NMDeviceClass *klass;
-
- nm_assert(NM_IS_DEVICE(self));
-
- klass = NM_DEVICE_GET_CLASS(self);
-
- if (klass->get_dhcp_anycast_address)
- return klass->get_dhcp_anycast_address(self);
-
- return NULL;
+ _dev_ip_state_check_async(self, addr_family);
}
static void
-dhcp4_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release)
+_dev_ipdhcpx_handle_accept(NMDevice *self, int addr_family, const NML3ConfigData *l3cd)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- priv->dhcp_data_4.was_active = FALSE;
- nm_clear_g_source(&priv->dhcp_data_4.grace_id);
- priv->dhcp_data_4.grace_pending = FALSE;
- nm_clear_g_free(&priv->dhcp4.pac_url);
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
- if (priv->dhcp_data_4.client) {
- /* Stop any ongoing DHCP transaction on this device */
- nm_clear_g_signal_handler(priv->dhcp_data_4.client, &priv->dhcp_data_4.notify_sigid);
+ _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_READY);
- if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED)
- nm_dhcp_client_stop(priv->dhcp_data_4.client, release);
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), l3cd, FALSE);
- g_clear_object(&priv->dhcp_data_4.client);
- }
+ nm_dhcp_config_set_lease(priv->ipdhcp_data_x[IS_IPv4].config, l3cd);
- if (priv->dhcp_data_4.config) {
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config);
- _notify(self, PROP_DHCP4_CONFIG);
- }
+ nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4),
+ self,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ _dev_ip_state_check_async(self, addr_family);
}
-static gboolean
-ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit)
+static void
+_dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gboolean success;
- gs_unref_object NMIPConfig *composite = NULL;
- NMIPConfig * config;
- gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
- NMConnection * connection;
- gboolean ignore_auto_routes = FALSE;
- gboolean ignore_auto_dns = FALSE;
- gboolean ignore_default_routes = FALSE;
- GSList * iter;
- const char * ip6_addr_gen_token = NULL;
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
-
- if (nm_device_sys_iface_state_is_external(self))
- commit = FALSE;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int addr_family = nm_dhcp_client_get_addr_family(client);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- connection = nm_device_get_applied_connection(self);
+ nm_assert(notify_data);
+ nm_assert(priv->ipdhcp_data_x[IS_IPv4].state > NM_DEVICE_IP_STATE_NONE);
+ nm_assert(client && priv->ipdhcp_data_x[IS_IPv4].client == client);
- /* Apply ignore-auto-routes and ignore-auto-dns settings */
- if (connection) {
- NMSettingIPConfig *s_ip;
+ switch (notify_data->notify_type) {
+ case NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED:
+ nm_assert(!IS_IPv4);
+ /* Just re-emit. The device just contributes the prefix to the
+ * pool in NMPolicy, which decides about subnet allocation
+ * on the shared devices. */
+ g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, notify_data->prefix_delegated.prefix);
+ return;
- s_ip = nm_connection_get_setting_ip_config(connection, addr_family);
- if (s_ip) {
- ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes(s_ip);
- ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns(s_ip);
+ case NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT:
+ /* Here we also fail if we had a lease and it expired. Maybe,
+ * ipv[46].dhcp-timeout should only cover the time until we get
+ * a lease for the first time. How it is here, it means that a
+ * connection can fail after being connected successfully for a
+ * longer time. */
+ _dev_ipdhcpx_handle_fail(self, addr_family, "timeout getting lease");
+ return;
- /* if the connection has an explicit gateway, we also ignore
- * the default routes from other sources. */
- ignore_default_routes = nm_setting_ip_config_get_never_default(s_ip)
- || nm_setting_ip_config_get_gateway(s_ip);
+ case NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD:
+ /* Like NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT, this does not
+ * apply only if we never got a lease, but also after being fully
+ * connected. We can also fail then. */
+ _dev_ipdhcpx_handle_fail(self, addr_family, notify_data->it_looks_bad.reason);
+ return;
- if (!IS_IPv4) {
- NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG(s_ip);
+ case NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE:
- if (nm_setting_ip6_config_get_addr_gen_mode(s_ip6)
- == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64)
- ip6_addr_gen_token = nm_setting_ip6_config_get_token(s_ip6);
- }
+ if (!notify_data->lease_update.l3cd) {
+ _LOGT_ipdhcp(addr_family, "lease lost");
+ _dev_ipdhcpx_handle_fail(self, addr_family, "lease lost");
+ return;
}
- }
-
- composite = nm_device_ip_config_new(self, addr_family);
- if (!IS_IPv4) {
- nm_ip6_config_set_privacy(NM_IP6_CONFIG(composite),
- priv->ndisc ? priv->ndisc_use_tempaddr
- : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+ _LOGT_ipdhcp(addr_family, "lease update");
+ _dev_ipdhcpx_handle_accept(self, addr_family, notify_data->lease_update.l3cd);
+ return;
}
- init_ip_config_dns_priority(self, composite);
+ nm_assert_not_reached();
+}
+
+/*****************************************************************************/
- if (commit) {
- if (priv->queued_ip_config_id_x[IS_IPv4])
- update_ext_ip_config(self, addr_family, FALSE);
- ensure_con_ip_config(self, addr_family);
+static void
+_dev_ipdhcpx_start(NMDevice *self, int addr_family)
+{
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMConnection * connection;
+ NMSettingConnection * s_con;
+ NMSettingIPConfig * s_ip;
+ const NML3ConfigData *previous_lease;
+ gs_unref_bytes GBytes *hwaddr = NULL;
+ gboolean enforce_duid = FALSE;
+ gs_free_error GError *error = NULL;
+ const NMPlatformLink *pllink;
+ guint no_lease_timeout_sec;
+ int ifindex;
+ const char * str;
+ gboolean request_broadcast;
+ const char * fail_reason;
+
+ if (priv->ipdhcp_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_NONE)
+ _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_PENDING);
+ else if (priv->ipdhcp_data_x[IS_IPv4].state > NM_DEVICE_IP_STATE_PENDING) {
+ /* already started. Nothing to do. */
+ return;
}
- if (!IS_IPv4) {
- if (commit && priv->ipv6ll_has) {
- const NMPlatformIP6Address ll_a = {
- .address = priv->ipv6ll_addr,
- .plen = 64,
- .addr_source = NM_IP_CONFIG_SOURCE_IP6LL,
- };
- const NMPlatformIP6Route ll_r = {
- .network.s6_addr16[0] = htons(0xfe80u),
- .plen = 64,
- .metric = nm_device_get_route_metric(self, addr_family),
- .rt_source = NM_IP_CONFIG_SOURCE_IP6LL,
- };
-
- nm_assert(IN6_IS_ADDR_LINKLOCAL(&priv->ipv6ll_addr));
-
- nm_ip6_config_add_address(NM_IP6_CONFIG(composite), &ll_a);
- nm_ip6_config_add_route(NM_IP6_CONFIG(composite), &ll_r, NULL);
- }
+ if (nm_device_sys_iface_state_is_external(self)) {
+ fail_reason = nm_assert_unreachable_val("cannot run DHCP on external interface");
+ goto out_fail;
}
- if (commit) {
- gboolean v;
-
- v = default_route_metric_penalty_detect(self, addr_family);
- if (IS_IPv4)
- priv->default_route_metric_penalty_ip4_has = v;
- else
- priv->default_route_metric_penalty_ip6_has = v;
+ connection = nm_device_get_applied_connection(self);
+ if (!connection) {
+ fail_reason = nm_assert_unreachable_val("no applied connection for starting DHCP");
+ goto out_fail;
}
- /* Merge all the IP configs into the composite config */
+ s_con = nm_connection_get_setting_connection(connection);
+ s_ip = nm_connection_get_setting_ip_config(connection, addr_family);
+ nm_assert(s_con);
+ nm_assert(s_ip);
- if (IS_IPv4) {
- config = applied_config_get_current(&priv->dev_ip_config_4);
- if (config) {
- nm_ip4_config_merge(
- NM_IP4_CONFIG(composite),
- NM_IP4_CONFIG(config),
- (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
- default_route_metric_penalty_get(self, addr_family));
- }
+ ifindex = 0;
+ pllink = nm_l3cfg_get_pllink(priv->l3cfg, TRUE);
+ if (pllink) {
+ ifindex = pllink->ifindex;
+ nm_assert(ifindex > 0);
+ nm_assert(ifindex == nm_device_get_ip_ifindex(self));
}
-
- if (!IS_IPv4) {
- config = applied_config_get_current(&priv->ac_ip6_config);
- if (config) {
- nm_ip6_config_merge(
- NM_IP6_CONFIG(composite),
- NM_IP6_CONFIG(config),
- (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
- default_route_metric_penalty_get(self, addr_family));
- }
+ if (ifindex <= 0) {
+ fail_reason = "cannot start DHCP without interface";
+ goto out_fail;
}
+ hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address);
+
if (!IS_IPv4) {
- config = applied_config_get_current(&priv->dhcp6.ip6_config);
- if (config) {
- nm_ip6_config_merge(
- NM_IP6_CONFIG(composite),
- NM_IP6_CONFIG(config),
- (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
- default_route_metric_penalty_get(self, addr_family));
+ if (!hwaddr) {
+ fail_reason = "interface has no MAC address to start DHCPv6";
+ goto out_fail;
}
}
- for (iter = priv->vpn_configs_x[IS_IPv4]; iter; iter = iter->next)
- nm_ip_config_merge(composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0);
-
- if (priv->ext_ip_config_x[IS_IPv4])
- nm_ip_config_merge(composite,
- priv->ext_ip_config_x[IS_IPv4],
- NM_IP_CONFIG_MERGE_EXTERNAL,
- 0);
-
- /* Merge WWAN config *last* to ensure modem-given settings overwrite
- * any external stuff set by pppd or other scripts.
- */
- config = applied_config_get_current(&priv->dev2_ip_config_x[IS_IPv4]);
- if (config) {
- nm_ip_config_merge(composite,
- config,
- (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
- default_route_metric_penalty_get(self, addr_family));
- }
-
- if (!IS_IPv4) {
- if (priv->rt6_temporary_not_available) {
- const NMPObject *o;
- GHashTableIter hiter;
-
- g_hash_table_iter_init(&hiter, priv->rt6_temporary_not_available);
- while (g_hash_table_iter_next(&hiter, (gpointer *) &o, NULL)) {
- nm_ip6_config_add_route(NM_IP6_CONFIG(composite),
- NMP_OBJECT_CAST_IP6_ROUTE(o),
- NULL);
- }
+ request_broadcast = FALSE;
+ if (pllink) {
+ str = nmp_object_link_udev_device_get_property_value(NMP_OBJECT_UP_CAST(pllink),
+ "ID_NET_DHCP_BROADCAST");
+ if (str && _nm_utils_ascii_str_to_bool(str, FALSE)) {
+ /* Use the device property ID_NET_DHCP_BROADCAST setting, which may be set for interfaces
+ * requiring that the DHCPOFFER message is being broadcast because they can't handle unicast
+ * messages while not fully configured.
+ */
+ request_broadcast = TRUE;
}
}
- /* Merge user overrides into the composite config. For assumed connections,
- * con_ip_config_x is empty. */
- if (priv->con_ip_config_x[IS_IPv4]) {
- nm_ip_config_merge(composite,
- priv->con_ip_config_x[IS_IPv4],
- NM_IP_CONFIG_MERGE_DEFAULT,
- default_route_metric_penalty_get(self, addr_family));
+ if (!IS_IPv4
+ && NM_IN_SET(priv->ipll_data_6.state,
+ NM_DEVICE_IP_STATE_NONE,
+ NM_DEVICE_IP_STATE_PENDING)) {
+ _dev_ipll6_start(self);
+ return;
}
- if (commit) {
- gboolean is_vrf;
+ no_lease_timeout_sec = _prop_get_ipvx_dhcp_timeout(self, addr_family);
+
+ if (IS_IPv4) {
+ NMDhcpClientConfig config;
+ gs_unref_bytes GBytes *bcast_hwaddr = NULL;
+ gs_unref_bytes GBytes *client_id = NULL;
+ gs_unref_bytes GBytes *vendor_class_identifier = NULL;
+ const char *const * reject_servers;
+ const char * hostname;
+ gboolean hostname_is_fqdn;
+
+ client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr);
+ vendor_class_identifier =
+ _prop_get_ipv4_dhcp_vendor_class_identifier(self, NM_SETTING_IP4_CONFIG(s_ip));
+ reject_servers = nm_setting_ip_config_get_dhcp_reject_servers(s_ip, NULL);
- is_vrf = priv->master && nm_device_get_device_type(priv->master) == NM_DEVICE_TYPE_VRF;
+ bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast);
- if (IS_IPv4) {
- nm_ip4_config_add_dependent_routes(NM_IP4_CONFIG(composite),
- nm_device_get_route_table(self, addr_family),
- nm_device_get_route_metric(self, addr_family),
- is_vrf,
- &ip4_dev_route_blacklist);
+ hostname = nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip));
+ if (hostname) {
+ hostname_is_fqdn = TRUE;
} else {
- nm_ip6_config_add_dependent_routes(NM_IP6_CONFIG(composite),
- nm_device_get_route_table(self, addr_family),
- nm_device_get_route_metric(self, addr_family),
- is_vrf);
+ hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip);
}
- }
- if (IS_IPv4) {
- if (commit) {
- if (NM_DEVICE_GET_CLASS(self)->ip4_config_pre_commit)
- NM_DEVICE_GET_CLASS(self)->ip4_config_pre_commit(self, NM_IP4_CONFIG(composite));
- }
- }
+ config = (NMDhcpClientConfig){
+ .addr_family = AF_INET,
+ .l3cfg = nm_device_get_l3cfg(self),
+ .iface = nm_device_get_ip_iface(self),
+ .uuid = nm_connection_get_uuid(connection),
+ .hwaddr = hwaddr,
+ .bcast_hwaddr = bcast_hwaddr,
+ .send_hostname = nm_setting_ip_config_get_dhcp_send_hostname(s_ip),
+ .hostname = hostname,
+ .hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET),
+ .client_id = client_id,
+ .mud_url = _prop_get_connection_mud_url(self, s_con),
+ .timeout = no_lease_timeout_sec,
+ .anycast_address = _device_get_dhcp_anycast_address(self),
+ .vendor_class_identifier = vendor_class_identifier,
+ .use_fqdn = hostname_is_fqdn,
+ .reject_servers = reject_servers,
+ .v4.request_broadcast = request_broadcast,
+ };
- if (!IS_IPv4) {
- NMUtilsIPv6IfaceId iid;
+ priv->ipdhcp_data_4.client =
+ nm_dhcp_manager_start_client(nm_dhcp_manager_get(), &config, &error);
+ } else {
+ gs_unref_bytes GBytes *duid = NULL;
+ gboolean iaid_explicit;
+ guint32 iaid;
+ NMDhcpClientConfig config;
- if (commit && priv->ndisc_started && ip6_addr_gen_token
- && nm_utils_ipv6_interface_identifier_get_from_token(&iid, ip6_addr_gen_token)) {
- set_ipv6_token(self, &iid, ip6_addr_gen_token);
+ if (!IN6_IS_ADDR_LINKLOCAL(&priv->ipll_data_6.v6.lladdr)) {
+ /* FIXME(l3cfg:dhcp): NMDhcpClient should monitor the IPv6 link local addresses.
+ * NMDevice kicks off NML3IPv6LL to generate an LL6 address, thereby trying
+ * that we have an LL address, but NMDhcpClient needs automatically monitor those
+ * addresses and choose a suitable one.
+ *
+ * This also means, NMDhcpClientConfig.v6.ll_addr needs to go away. */
+ fail_reason = "interface has no IPv6 link local address to start DHCPv6";
+ goto out_fail;
}
- }
- success =
- nm_device_set_ip_config(self, addr_family, composite, commit, ip4_dev_route_blacklist);
- if (commit) {
- if (IS_IPv4)
- priv->v4_commit_first_time = FALSE;
- else
- priv->v6_commit_first_time = FALSE;
- }
-
- return success;
-}
+ iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, FALSE, &iaid_explicit);
+ duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid);
+
+ config = (NMDhcpClientConfig){
+ .addr_family = AF_INET6,
+ .l3cfg = nm_device_get_l3cfg(self),
+ .iface = nm_device_get_ip_iface(self),
+ .uuid = nm_connection_get_uuid(connection),
+ .send_hostname = nm_setting_ip_config_get_dhcp_send_hostname(s_ip),
+ .hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip),
+ .hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6),
+ .client_id = duid,
+ .mud_url = _prop_get_connection_mud_url(self, s_con),
+ .timeout = no_lease_timeout_sec,
+ .anycast_address = _device_get_dhcp_anycast_address(self),
+ .v6.ll_addr = &priv->ipll_data_6.v6.lladdr,
+ .v6.enforce_duid = enforce_duid,
+ .v6.iaid = iaid,
+ .v6.iaid_explicit = iaid_explicit,
+ .v6.info_only = (priv->ipdhcp_data_6.v6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF),
+ .v6.needed_prefixes = priv->ipdhcp_data_6.v6.needed_prefixes,
+ };
-static gboolean
-dhcp4_lease_change(NMDevice *self, NMIP4Config *config, gboolean bound)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gs_free_error GError *error = NULL;
+ priv->ipdhcp_data_6.client =
+ nm_dhcp_manager_start_client(nm_dhcp_manager_get(), &config, &error);
+ }
- g_return_val_if_fail(config, FALSE);
+ if (!priv->ipdhcp_data_x[IS_IPv4].client) {
+ fail_reason = error->message;
+ goto out_fail;
+ }
- applied_config_init(&priv->dev_ip_config_4, config);
+ priv->ipdhcp_data_x[IS_IPv4].notify_sigid =
+ g_signal_connect(priv->ipdhcp_data_x[IS_IPv4].client,
+ NM_DHCP_CLIENT_NOTIFY,
+ G_CALLBACK(_dev_ipdhcpx_notify),
+ self);
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) {
- _LOGW(LOGD_DHCP4, "failed to update IPv4 config for DHCP change.");
- return FALSE;
- }
+ /* FIXME(l3cfg:dhcp:previous-lease): take the NML3ConfigData from the previous lease (if any)
+ * and pass it on to NMDhcpClient. This is a fake lease that we use initially (until
+ * NMDhcpClient got a real lease). Note that NMDhcpClient needs to check whether the
+ * lease already expired. */
- /* TODO: we should perform DAD again whenever we obtain a
- * new lease after an expiry. But what should we do if
- * a duplicate address is detected? Fail the connection;
- * restart DHCP; continue without an address? */
- if (bound && !nm_dhcp_client_accept(priv->dhcp_data_4.client, &error)) {
- _LOGW(LOGD_DHCP4, "error accepting lease: %s", error->message);
- return FALSE;
+ previous_lease = nm_dhcp_client_get_lease(priv->ipdhcp_data_x[IS_IPv4].client);
+ if (!priv->ipdhcp_data_x[IS_IPv4].config) {
+ priv->ipdhcp_data_x[IS_IPv4].config = nm_dhcp_config_new(addr_family, previous_lease);
+ _notify(self, PROP_DHCPX_CONFIG(IS_IPv4));
}
+ if (previous_lease)
+ _dev_ipdhcpx_handle_accept(self, addr_family, previous_lease);
- nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_4, self, NULL, NULL, NULL, NULL);
+ return;
- return TRUE;
+out_fail:
+ _dev_ipdhcpx_handle_fail(self, addr_family, fail_reason);
}
-static gboolean
-dhcp_grace_period_expired(NMDevice *self, int addr_family)
+static void
+_dev_ipdhcpx_start_continue(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
- priv->dhcp_data_x[IS_IPv4].grace_id = 0;
- priv->dhcp_data_x[IS_IPv4].grace_pending = FALSE;
-
- _LOGI(LOGD_DHCPX(IS_IPv4),
- "DHCPv%c: grace period expired",
- nm_utils_addr_family_to_char(addr_family));
-
- nm_device_ip_method_failed(self, addr_family, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
- /* If the device didn't fail, the DHCP client will continue */
-
- return G_SOURCE_REMOVE;
+ if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_NONE)
+ _dev_ipdhcpx_start(self, addr_family);
}
-static gboolean
-dhcp_grace_period_expired_4(gpointer user_data)
-{
- return dhcp_grace_period_expired(user_data, AF_INET);
-}
-
-static gboolean
-dhcp_grace_period_expired_6(gpointer user_data)
-{
- return dhcp_grace_period_expired(user_data, AF_INET6);
-}
-
-static gboolean
-dhcp_grace_period_start(NMDevice *self, int addr_family)
+static void
+_dev_ipdhcpx_restart(NMDevice *self, int addr_family, gboolean release)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
- guint32 timeout;
- /* In any other case (expired lease, assumed connection, etc.),
- * wait for some time before failing the IP method.
- */
- if (priv->dhcp_data_x[IS_IPv4].grace_pending) {
- /* already pending. */
- return FALSE;
+ if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_NONE) {
+ _LOGI_ipdhcp(addr_family, "restarting%s", release ? " (release lease)" : "");
+ _dev_ipdhcpx_cleanup(self, addr_family, FALSE, release);
}
- /* Start a grace period equal to the DHCP timeout multiplied
- * by a constant factor. */
- timeout = _prop_get_ipvx_dhcp_timeout(self, addr_family);
- if (timeout == NM_DHCP_TIMEOUT_INFINITY)
- _LOGI(LOGD_DHCPX(IS_IPv4),
- "DHCPv%c: trying to acquire a new lease",
- nm_utils_addr_family_to_char(addr_family));
- else {
- timeout = dhcp_grace_period_from_timeout(timeout);
- _LOGI(LOGD_DHCPX(IS_IPv4),
- "DHCPv%c: trying to acquire a new lease within %u seconds",
- nm_utils_addr_family_to_char(addr_family),
- timeout);
- nm_assert(!priv->dhcp_data_x[IS_IPv4].grace_id);
- priv->dhcp_data_x[IS_IPv4].grace_id = g_timeout_add_seconds(
- timeout,
- IS_IPv4 ? dhcp_grace_period_expired_4 : dhcp_grace_period_expired_6,
- self);
- }
-
- priv->dhcp_data_x[IS_IPv4].grace_pending = TRUE;
-
- return TRUE;
-}
-static void
-dhcp4_fail(NMDevice *self, NMDhcpState dhcp_state)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- _LOGD(LOGD_DHCP4,
- "DHCPv4 failed (ip_state %s, was_active %d)",
- nm_device_ip_state_to_string(priv->ip_state_4),
- priv->dhcp_data_4.was_active);
-
- /* The client is always left running after a failure. */
-
- /* Nothing to do if we failed before... */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL)
- goto clear_config;
-
- /* ... and also if there are static addresses configured
- * on the interface.
- */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && priv->con_ip_config_4
- && nm_ip4_config_get_num_addresses(priv->con_ip_config_4) > 0)
- goto clear_config;
-
- /* Fail the method when one of the following is true:
- * 1) the DHCP client terminated: it does not make sense to start a grace
- * period without a client running;
- * 2) we failed to get an initial lease AND the client was
- * not active before.
- */
- if (dhcp_state == NM_DHCP_STATE_TERMINATED
- || (!priv->dhcp_data_4.was_active && priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)) {
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET);
- return;
- }
-
- if (dhcp_grace_period_start(self, AF_INET))
- goto clear_config;
-
- return;
-
-clear_config:
- /* The previous configuration is no longer valid */
- if (priv->dhcp_data_4.config) {
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config);
- priv->dhcp_data_4.config = nm_dhcp_config_new(AF_INET);
- _notify(self, PROP_DHCP4_CONFIG);
- }
-}
-
-static void
-dhcp4_dad_cb(NMDevice *self, NMIP4Config **configs, gboolean success)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- if (success) {
- nm_device_activate_schedule_ip_config_result(self, AF_INET, NM_IP_CONFIG_CAST(configs[1]));
- } else {
- nm_dhcp_client_decline(priv->dhcp_data_4.client, "Address conflict detected", NULL);
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE);
- }
+ _dev_ipdhcpx_start(self, addr_family);
}
static void
-dhcp4_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self)
+_dev_ipdhcp6_set_dhcp_level(NMDevice *self, NMNDiscDHCPLevel dhcp_level)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMIP4Config * manual;
- NMIP4Config ** configs;
- NMConnection * connection;
- NMDhcpState state;
- NMIP4Config * ip4_config;
- GHashTable * options;
-
- nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET);
- nm_assert(notify_data);
- nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED);
-
- state = notify_data->state_changed.dhcp_state;
- ip4_config = NM_IP4_CONFIG(notify_data->state_changed.ip_config);
- options = notify_data->state_changed.options;
-
- nm_assert(!ip4_config || NM_IS_IP4_CONFIG(ip4_config));
-
- _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", (int) state);
-
- switch (state) {
- case NM_DHCP_STATE_BOUND:
- case NM_DHCP_STATE_EXTENDED:
- if (!ip4_config) {
- _LOGW(LOGD_DHCP4, "failed to get IPv4 config in response to DHCP event.");
- dhcp4_fail(self, state);
- break;
- }
-
- nm_clear_g_source(&priv->dhcp_data_4.grace_id);
- priv->dhcp_data_4.grace_pending = FALSE;
-
- /* After some failures, we have been able to renew the lease:
- * update the ip state
- */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL)
- _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_CONF);
-
- g_free(priv->dhcp4.pac_url);
- priv->dhcp4.pac_url = g_strdup(g_hash_table_lookup(options, "wpad"));
- nm_device_set_proxy_config(self, priv->dhcp4.pac_url);
-
- nm_dhcp_config_set_options(priv->dhcp_data_4.config, options);
- _notify(self, PROP_DHCP4_CONFIG);
-
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF) {
- connection = nm_device_get_applied_connection(self);
- g_assert(connection);
-
- manual = nm_device_ip4_config_new(self);
- nm_ip4_config_merge_setting(manual,
- nm_connection_get_setting_ip4_config(connection),
- NM_SETTING_CONNECTION_MDNS_DEFAULT,
- NM_SETTING_CONNECTION_LLMNR_DEFAULT,
- nm_device_get_route_table(self, AF_INET),
- nm_device_get_route_metric(self, AF_INET));
-
- configs = g_new0(NMIP4Config *, 3);
- configs[0] = manual;
- configs[1] = g_object_ref(ip4_config);
-
- ipv4_dad_start(self, configs, dhcp4_dad_cb);
- } else if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) {
- if (dhcp4_lease_change(self, ip4_config, state == NM_DHCP_STATE_BOUND))
- nm_device_update_metered(self);
- else
- dhcp4_fail(self, state);
- }
- break;
- case NM_DHCP_STATE_TIMEOUT:
- dhcp4_fail(self, state);
- break;
- case NM_DHCP_STATE_EXPIRE:
- /* Ignore expiry before we even have a lease (NAK, old lease, etc) */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)
- break;
- /* fall-through */
- case NM_DHCP_STATE_DONE:
- case NM_DHCP_STATE_FAIL:
- case NM_DHCP_STATE_TERMINATED:
- dhcp4_fail(self, state);
- break;
- default:
- break;
- }
-}
-static NMActStageReturn
-dhcp4_start(NMDevice *self)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMSettingIPConfig *s_ip4;
- gs_unref_bytes GBytes *vendor_class_identifier = NULL;
- gs_unref_bytes GBytes *hwaddr = NULL;
- gs_unref_bytes GBytes *bcast_hwaddr = NULL;
- gs_unref_bytes GBytes *client_id = NULL;
- NMConnection * connection;
- NMSettingConnection * s_con;
- GError * error = NULL;
- const NMPlatformLink * pllink;
- const char *const * reject_servers;
- gboolean request_broadcast;
- const char * str;
+ nm_assert(NM_IN_SET(dhcp_level,
+ NM_NDISC_DHCP_LEVEL_NONE,
+ NM_NDISC_DHCP_LEVEL_OTHERCONF,
+ NM_NDISC_DHCP_LEVEL_MANAGED));
- connection = nm_device_get_applied_connection(self);
- g_return_val_if_fail(connection, FALSE);
+ if (dhcp_level == NM_NDISC_DHCP_LEVEL_NONE && priv->ipdhcp_data_6.v6.needed_prefixes > 0)
+ dhcp_level = NM_NDISC_DHCP_LEVEL_OTHERCONF;
- s_ip4 = nm_connection_get_setting_ip4_config(connection);
-
- s_con = nm_connection_get_setting_connection(connection);
- nm_assert(s_con);
-
- /* Clear old exported DHCP options */
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config);
- priv->dhcp_data_4.config = nm_dhcp_config_new(AF_INET);
-
- request_broadcast = FALSE;
+ if (priv->ipdhcp_data_6.v6.mode == dhcp_level)
+ return;
- pllink = nm_platform_link_get(nm_device_get_platform(self), nm_device_get_ip_ifindex(self));
- if (pllink) {
- hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address);
- bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast);
+ _LOGD_ipdhcp(AF_INET6, "level: set to %s", nm_ndisc_dhcp_level_to_string(dhcp_level));
- str = nmp_object_link_udev_device_get_property_value(NMP_OBJECT_UP_CAST(pllink),
- "ID_NET_DHCP_BROADCAST");
- if (str && _nm_utils_ascii_str_to_bool(str, FALSE)) {
- /* Use the device property ID_NET_DHCP_BROADCAST setting, which may be set for interfaces
- * requiring that the DHCPOFFER message is being broadcast because they can't handle unicast
- * messages while not fully configured.
- */
- request_broadcast = TRUE;
- }
+ if (dhcp_level == NM_NDISC_DHCP_LEVEL_NONE) {
+ _dev_ipdhcpx_cleanup(self, AF_INET6, TRUE, TRUE);
+ return;
}
- client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr);
- vendor_class_identifier =
- _prop_get_ipv4_dhcp_vendor_class_identifier(self, NM_SETTING_IP4_CONFIG(s_ip4));
- reject_servers = nm_setting_ip_config_get_dhcp_reject_servers(s_ip4, NULL);
-
- g_warn_if_fail(priv->dhcp_data_4.client == NULL);
- priv->dhcp_data_4.client = nm_dhcp_manager_start_ip4(
- nm_dhcp_manager_get(),
- nm_netns_get_multi_idx(nm_device_get_netns(self)),
- nm_device_get_ip_iface(self),
- nm_device_get_ip_ifindex(self),
- hwaddr,
- bcast_hwaddr,
- nm_connection_get_uuid(connection),
- nm_device_get_route_table(self, AF_INET),
- nm_device_get_route_metric(self, AF_INET),
- request_broadcast ? NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST : NM_DHCP_CLIENT_FLAGS_NONE,
- nm_setting_ip_config_get_dhcp_send_hostname(s_ip4),
- nm_setting_ip_config_get_dhcp_hostname(s_ip4),
- nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip4)),
- _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET),
- _prop_get_connection_mud_url(self, s_con),
- client_id,
- _prop_get_ipvx_dhcp_timeout(self, AF_INET),
- _device_get_dhcp_anycast_address(self),
- NULL,
- vendor_class_identifier,
- reject_servers,
- &error);
- if (!priv->dhcp_data_4.client) {
- _LOGW(LOGD_DHCP4, "failure to start DHCP: %s", error->message);
- g_clear_error(&error);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
-
- priv->dhcp_data_4.notify_sigid = g_signal_connect(priv->dhcp_data_4.client,
- NM_DHCP_CLIENT_NOTIFY,
- G_CALLBACK(dhcp4_notify),
- self);
-
- if (nm_device_sys_iface_state_is_external_or_assume(self))
- priv->dhcp_data_4.was_active = TRUE;
-
- /* DHCP devices will be notified by the DHCP manager when stuff happens */
- return NM_ACT_STAGE_RETURN_POSTPONE;
+ priv->ipdhcp_data_6.v6.mode = dhcp_level;
+ _dev_ipdhcpx_restart(self, AF_INET6, TRUE);
}
-gboolean
-nm_device_dhcp4_renew(NMDevice *self, gboolean release)
+/*
+ * Called on the requesting interface when a subnet can't be obtained
+ * from known prefixes for a newly active shared connection.
+ */
+void
+nm_device_request_ip6_prefixes(NMDevice *self, guint needed_prefixes)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- g_return_val_if_fail(priv->dhcp_data_4.client != NULL, FALSE);
-
- _LOGI(LOGD_DHCP4, "DHCPv4 lease renewal requested");
-
- /* Terminate old DHCP instance and release the old lease */
- dhcp4_cleanup(self, CLEANUP_TYPE_DECONFIGURE, release);
-
- /* Start DHCP again on the interface */
- return dhcp4_start(self) != NM_ACT_STAGE_RETURN_FAILURE;
-}
-
-/*****************************************************************************/
-
-static NMIP4Config *
-shared4_new_config(NMDevice *self, NMConnection *connection)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMIP4Config * config;
- NMSettingIPConfig * s_ip4;
- NMPlatformIP4Address address = {
- .addr_source = NM_IP_CONFIG_SOURCE_SHARED,
- };
+ if (priv->ipdhcp_data_6.v6.needed_prefixes == needed_prefixes)
+ return;
- g_return_val_if_fail(self, NULL);
- g_return_val_if_fail(connection, NULL);
+ _LOGD(LOGD_IP6, "ipv6-pd: asking DHCPv6 for %u prefixes", needed_prefixes);
- s_ip4 = nm_connection_get_setting_ip4_config(connection);
- if (s_ip4 && nm_setting_ip_config_get_num_addresses(s_ip4) > 0) {
- /* Use the first user-supplied address */
- NMIPAddress *user = nm_setting_ip_config_get_address(s_ip4, 0);
- in_addr_t a;
+ priv->ipdhcp_data_6.v6.needed_prefixes = needed_prefixes;
- nm_ip_address_get_address_binary(user, &a);
- nm_platform_ip4_address_set_addr(&address, a, nm_ip_address_get_prefix(user));
- nm_clear_pointer(&priv->shared_ip_handle, nm_netns_shared_ip_release);
- } else {
- if (!priv->shared_ip_handle)
- priv->shared_ip_handle = nm_netns_shared_ip_reserve(nm_device_get_netns(self));
- nm_platform_ip4_address_set_addr(&address, priv->shared_ip_handle->addr, 24);
+ if (priv->ipdhcp_data_6.v6.mode == NM_NDISC_DHCP_LEVEL_NONE) {
+ priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_OTHERCONF;
+ _LOGD_ipdhcp(AF_INET6,
+ "level: set to %s",
+ nm_ndisc_dhcp_level_to_string(NM_NDISC_DHCP_LEVEL_OTHERCONF));
}
- config = nm_device_ip4_config_new(self);
- nm_ip4_config_add_address(config, &address);
-
- return config;
+ _dev_ipdhcpx_restart(self, AF_INET6, TRUE);
}
/*****************************************************************************/
@@ -9766,392 +10050,6 @@ have_any_ready_slaves(NMDevice *self)
}
/*****************************************************************************/
-/* DHCPv6 stuff */
-
-static void
-dhcp6_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- priv->dhcp_data_6.was_active = FALSE;
- priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE;
- applied_config_clear(&priv->dhcp6.ip6_config);
- nm_clear_g_free(&priv->dhcp6.event_id);
- nm_clear_g_source(&priv->dhcp_data_6.grace_id);
- priv->dhcp_data_6.grace_pending = FALSE;
-
- if (priv->dhcp_data_6.client) {
- nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp_data_6.notify_sigid);
-
- if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED)
- nm_dhcp_client_stop(priv->dhcp_data_6.client, release);
-
- g_clear_object(&priv->dhcp_data_6.client);
- }
-
- if (priv->dhcp_data_6.config) {
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config);
- _notify(self, PROP_DHCP6_CONFIG);
- }
-}
-
-static gboolean
-dhcp6_lease_change(NMDevice *self)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMSettingsConnection *settings_connection;
-
- if (!applied_config_get_current(&priv->dhcp6.ip6_config)) {
- _LOGW(LOGD_DHCP6, "failed to get DHCPv6 config for rebind");
- return FALSE;
- }
-
- g_assert(priv->dhcp_data_6.client); /* sanity check */
-
- settings_connection = nm_device_get_settings_connection(self);
- g_assert(settings_connection);
-
- /* Apply the updated config */
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) {
- _LOGW(LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event");
- return FALSE;
- }
-
- nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_6, self, NULL, NULL, NULL, NULL);
-
- return TRUE;
-}
-
-static void
-dhcp6_fail(NMDevice *self, NMDhcpState dhcp_state)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gboolean is_dhcp_managed;
-
- _LOGD(LOGD_DHCP6,
- "DHCPv6 failed (ip_state %s, was_active %d)",
- nm_device_ip_state_to_string(priv->ip_state_6),
- priv->dhcp_data_6.was_active);
-
- /* The client is always left running after a failure. */
-
- /* Nothing to do if we failed before... */
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL)
- goto clear_config;
-
- is_dhcp_managed = (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED);
-
- if (is_dhcp_managed) {
- /* ... and also if there are static addresses configured
- * on the interface.
- */
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE && priv->con_ip_config_6
- && nm_ip6_config_get_num_addresses(priv->con_ip_config_6))
- goto clear_config;
-
- /* Fail the method when one of the following is true:
- * 1) the DHCP client terminated: it does not make sense to start a grace
- * period without a client running;
- * 2) we failed to get an initial lease AND the client was
- * not active before.
- */
- if (dhcp_state == NM_DHCP_STATE_TERMINATED
- || (!priv->dhcp_data_6.was_active && priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF)) {
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET6);
- return;
- }
-
- if (dhcp_grace_period_start(self, AF_INET6))
- goto clear_config;
- } else {
- /* not a hard failure; just live with the RA info */
- dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, FALSE);
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF)
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- }
- return;
-
-clear_config:
- /* The previous configuration is no longer valid */
- if (priv->dhcp_data_6.config) {
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config);
- priv->dhcp_data_6.config = nm_dhcp_config_new(AF_INET6);
- _notify(self, PROP_DHCP6_CONFIG);
- }
-}
-
-static void
-dhcp6_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gs_free char * event_id = NULL;
- NMDhcpState state;
- NMIP6Config * ip6_config;
- GHashTable * options;
-
- nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET6);
- nm_assert(notify_data);
-
- if (notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED) {
- /* Just re-emit. The device just contributes the prefix to the
- * pool in NMPolicy, which decides about subnet allocation
- * on the shared devices. */
- g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, notify_data->prefix_delegated.prefix);
- return;
- }
-
- nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED);
-
- state = notify_data->state_changed.dhcp_state;
- ip6_config = NM_IP6_CONFIG(notify_data->state_changed.ip_config);
- options = notify_data->state_changed.options;
-
- nm_assert(!ip6_config || NM_IS_IP6_CONFIG(ip6_config));
-
- _LOGD(LOGD_DHCP6, "new DHCPv6 client state %d", (int) state);
-
- switch (state) {
- case NM_DHCP_STATE_BOUND:
- case NM_DHCP_STATE_EXTENDED:
- nm_clear_g_source(&priv->dhcp_data_6.grace_id);
- priv->dhcp_data_6.grace_pending = FALSE;
- /* If the server sends multiple IPv6 addresses, we receive a state
- * changed event for each of them. Use the event ID to merge IPv6
- * addresses from the same transaction into a single configuration.
- */
-
- event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
-
- if (ip6_config && event_id && priv->dhcp6.event_id
- && nm_streq(event_id, priv->dhcp6.event_id)) {
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *a;
-
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6_config, &a)
- applied_config_add_address(&priv->dhcp6.ip6_config, NM_PLATFORM_IP_ADDRESS_CAST(a));
- } else {
- nm_clear_g_free(&priv->dhcp6.event_id);
- if (ip6_config) {
- applied_config_init(&priv->dhcp6.ip6_config, ip6_config);
- priv->dhcp6.event_id = g_strdup(event_id);
- nm_dhcp_config_set_options(priv->dhcp_data_6.config, options);
- _notify(self, PROP_DHCP6_CONFIG);
- } else
- applied_config_clear(&priv->dhcp6.ip6_config);
- }
-
- /* After long time we have been able to renew the lease:
- * update the ip state
- */
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL)
- _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_CONF);
-
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) {
- if (!applied_config_get_current(&priv->dhcp6.ip6_config)) {
- nm_device_ip_method_failed(self, AF_INET6, NM_DEVICE_STATE_REASON_DHCP_FAILED);
- break;
- }
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- } else if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE)
- if (!dhcp6_lease_change(self))
- dhcp6_fail(self, state);
- break;
- case NM_DHCP_STATE_TIMEOUT:
- if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED)
- dhcp6_fail(self, state);
- else {
- /* not a hard failure; just live with the RA info */
- dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, FALSE);
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF)
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- }
- break;
- case NM_DHCP_STATE_EXPIRE:
- /* Ignore expiry before we even have a lease (NAK, old lease, etc) */
- if (priv->ip_state_6 != NM_DEVICE_IP_STATE_CONF)
- dhcp6_fail(self, state);
- break;
- case NM_DHCP_STATE_TERMINATED:
- /* In IPv6 info-only mode, the client doesn't handle leases so it
- * may exit right after getting a response from the server. That's
- * normal. In that case we just ignore the exit.
- */
- if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF)
- break;
- /* fall-through */
- case NM_DHCP_STATE_DONE:
- case NM_DHCP_STATE_FAIL:
- dhcp6_fail(self, state);
- break;
- default:
- break;
- }
-}
-
-/*****************************************************************************/
-
-static gboolean
-dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMSettingIPConfig *s_ip6;
- gs_unref_bytes GBytes *hwaddr = NULL;
- gs_unref_bytes GBytes * duid = NULL;
- gboolean enforce_duid = FALSE;
- const NMPlatformLink * pllink;
- GError * error = NULL;
- guint32 iaid;
- gboolean iaid_explicit;
- NMSettingConnection * s_con;
- const NMPlatformIP6Address *ll_addr = NULL;
- int ip_ifindex;
-
- g_return_val_if_fail(connection, FALSE);
-
- s_ip6 = nm_connection_get_setting_ip6_config(connection);
- nm_assert(s_ip6);
- s_con = nm_connection_get_setting_connection(connection);
- nm_assert(s_con);
-
- if (priv->ext_ip6_config_captured) {
- ll_addr = nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured),
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL);
- }
-
- if (!ll_addr) {
- _LOGW(LOGD_DHCP6, "can't start DHCPv6: no link-local address");
- return FALSE;
- }
-
- ip_ifindex = nm_device_get_ip_ifindex(self);
- if (ip_ifindex <= 0) {
- _LOGD(LOGD_DHCP6, "can't start DHCPv6: interface is gone");
- return FALSE;
- }
-
- pllink = nm_platform_link_get(nm_device_get_platform(self), ip_ifindex);
- if (pllink)
- hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address);
-
- iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, TRUE, &iaid_explicit);
- duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid);
-
- priv->dhcp_data_6.client = nm_dhcp_manager_start_ip6(
- nm_dhcp_manager_get(),
- nm_device_get_multi_index(self),
- nm_device_get_ip_iface(self),
- ip_ifindex,
- &ll_addr->address,
- nm_connection_get_uuid(connection),
- nm_device_get_route_table(self, AF_INET6),
- nm_device_get_route_metric(self, AF_INET6),
- (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY
- : NM_DHCP_CLIENT_FLAGS_NONE,
- nm_setting_ip_config_get_dhcp_send_hostname(s_ip6),
- nm_setting_ip_config_get_dhcp_hostname(s_ip6),
- _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6),
- _prop_get_connection_mud_url(self, s_con),
- duid,
- enforce_duid,
- iaid,
- iaid_explicit,
- _prop_get_ipvx_dhcp_timeout(self, AF_INET6),
- _device_get_dhcp_anycast_address(self),
- nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip6)),
- priv->dhcp6.needed_prefixes,
- &error);
- if (!priv->dhcp_data_6.client) {
- _LOGW(LOGD_DHCP6, "failure to start DHCPv6: %s", error->message);
- g_clear_error(&error);
- if (nm_device_sys_iface_state_is_external_or_assume(self))
- priv->dhcp_data_6.was_active = TRUE;
- return FALSE;
- }
-
- priv->dhcp_data_6.notify_sigid = g_signal_connect(priv->dhcp_data_6.client,
- NM_DHCP_CLIENT_NOTIFY,
- G_CALLBACK(dhcp6_notify),
- self);
-
- if (nm_device_sys_iface_state_is_external_or_assume(self))
- priv->dhcp_data_6.was_active = TRUE;
-
- return TRUE;
-}
-
-static gboolean
-dhcp6_start(NMDevice *self, gboolean wait_for_ll)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMConnection * connection;
-
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config);
- priv->dhcp_data_6.config = nm_dhcp_config_new(AF_INET6);
-
- nm_assert(!applied_config_get_current(&priv->dhcp6.ip6_config));
- applied_config_clear(&priv->dhcp6.ip6_config);
- nm_clear_g_free(&priv->dhcp6.event_id);
-
- connection = nm_device_get_applied_connection(self);
- g_return_val_if_fail(connection, FALSE);
-
- if (wait_for_ll) {
- /* ensure link local is ready... */
- if (!linklocal6_start(self)) {
- /* wait for the LL address to show up */
- return TRUE;
- }
- /* already have the LL address; kick off DHCP */
- }
-
- if (!dhcp6_start_with_link_ready(self, connection))
- return FALSE;
-
- return TRUE;
-}
-
-gboolean
-nm_device_dhcp6_renew(NMDevice *self, gboolean release)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMNDiscDHCPLevel mode;
-
- g_return_val_if_fail(priv->dhcp_data_6.client != NULL, FALSE);
-
- _LOGI(LOGD_DHCP6, "DHCPv6 lease renewal requested");
-
- /* Terminate old DHCP instance and release the old lease */
- mode = priv->dhcp6.mode;
- dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, release);
- priv->dhcp6.mode = mode;
-
- /* Start DHCP again on the interface */
- return dhcp6_start(self, FALSE);
-}
-
-/*****************************************************************************/
-
-/*
- * Called on the requesting interface when a subnet can't be obtained
- * from known prefixes for a newly active shared connection.
- */
-void
-nm_device_request_ip6_prefixes(NMDevice *self, int needed_prefixes)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- priv->dhcp6.needed_prefixes = needed_prefixes;
-
- if (priv->dhcp_data_6.client) {
- _LOGD(LOGD_IP6, "ipv6-pd: asking DHCPv6 for %d prefixes", needed_prefixes);
- nm_device_dhcp6_renew(self, FALSE);
- } else {
- priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_OTHERCONF;
- _LOGD(LOGD_DEVICE | LOGD_DHCP6, "ipv6-pd: starting DHCPv6 to request a prefix");
- dhcp6_start(self, FALSE);
- }
-}
gboolean
nm_device_needs_ip6_subnet(NMDevice *self)
@@ -10166,25 +10064,24 @@ nm_device_needs_ip6_subnet(NMDevice *self)
void
nm_device_use_ip6_subnet(NMDevice *self, const NMPlatformIP6Address *subnet)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMPlatformIP6Address address = *subnet;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ char sbuf[sizeof(_nm_utils_to_string_buffer)];
+ NMPlatformIP6Address address;
- if (!applied_config_get_current(&priv->ac_ip6_config))
- applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6);
+ l3cd = nm_device_create_l3_config_data(self, NM_IP_CONFIG_SOURCE_SHARED);
/* Assign a ::1 address in the subnet for us. */
+ address = *subnet;
address.address.s6_addr32[3] |= htonl(1);
- applied_config_add_address(&priv->ac_ip6_config, NM_PLATFORM_IP_ADDRESS_CAST(&address));
+
+ nm_l3_config_data_add_address_6(l3cd, &address);
_LOGD(LOGD_IP6,
- "ipv6-pd: using %s address (preferred for %u seconds)",
- _nm_utils_inet6_ntop(&address.address, sbuf),
- subnet->preferred);
+ "ipv6-pd: using %s",
+ nm_platform_ip6_address_to_string(&address, sbuf, sizeof(sbuf)));
- /* This also updates the ndisc if there are actual changes. */
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "ipv6-pd: failed applying IP6 config for connection sharing");
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_PD_6, l3cd, FALSE);
+ _dev_l3_cfg_commit(self, TRUE);
}
/*
@@ -10194,137 +10091,184 @@ nm_device_use_ip6_subnet(NMDevice *self, const NMPlatformIP6Address *subnet)
void
nm_device_copy_ip6_dns_config(NMDevice *self, NMDevice *from_device)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMIP6Config * from_config = NULL;
- guint i, len;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDevicePrivate * priv_src;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ const NML3ConfigData * l3cd_src;
- if (applied_config_get_current(&priv->ac_ip6_config)) {
- applied_config_reset_nameservers(&priv->ac_ip6_config);
- applied_config_reset_searches(&priv->ac_ip6_config);
+ /* FIXME(l3cfg): this entire code an approach seems flawed. It's flawed, because the
+ * very next RA will reset the changes. */
+
+ if (priv->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d) {
+ l3cd = nm_l3_config_data_new_clone(priv->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d, 0);
+ nm_l3_config_data_clear_nameservers(l3cd, AF_INET6);
+ nm_l3_config_data_clear_searches(l3cd, AF_INET6);
} else
- applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6);
+ l3cd = nm_device_create_l3_config_data(self, NM_IP_CONFIG_SOURCE_SHARED);
- if (from_device)
- from_config = nm_device_get_ip6_config(from_device);
- if (!from_config)
- return;
+ priv_src = NM_DEVICE_GET_PRIVATE(from_device);
+ l3cd_src = priv_src->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d;
+ if (l3cd_src) {
+ const char *const * strvarr;
+ const struct in6_addr *const *addrs;
+ guint n;
+ guint i;
- len = nm_ip6_config_get_num_nameservers(from_config);
- for (i = 0; i < len; i++) {
- applied_config_add_nameserver(
- &priv->ac_ip6_config,
- (const NMIPAddr *) nm_ip6_config_get_nameserver(from_config, i));
- }
+ addrs = nm_l3_config_data_get_nameservers(l3cd_src, AF_INET6, &n);
+ for (i = 0; i < n; i++)
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, addrs[i]);
- len = nm_ip6_config_get_num_searches(from_config);
- for (i = 0; i < len; i++) {
- applied_config_add_search(&priv->ac_ip6_config, nm_ip6_config_get_search(from_config, i));
+ strvarr = nm_l3_config_data_get_searches(l3cd_src, AF_INET6, &n);
+ for (i = 0; i < n; i++)
+ nm_l3_config_data_add_search(l3cd, AF_INET6, strvarr[i]);
}
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "ipv6-pd: failed applying DNS config for connection sharing");
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_AC_6, l3cd, FALSE);
+
+ _dev_l3_cfg_commit(self, TRUE);
}
/*****************************************************************************/
-static void
-linklocal6_failed(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- nm_clear_g_source(&priv->linklocal6_timeout_id);
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET6);
-}
-
static gboolean
-linklocal6_timeout_cb(gpointer user_data)
+_dev_ipll6_state_retry_cb(gpointer user_data)
{
- NMDevice *self = user_data;
+ NMDevice * self = user_data;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- _LOGD(LOGD_DEVICE, "linklocal6: waiting for link-local addresses failed due to timeout");
- linklocal6_failed(self);
- return G_SOURCE_REMOVE;
+ nm_clear_g_source_inst(&priv->ipll_data_6.v6.retry_source);
+ _dev_ipll6_start(self);
+ return G_SOURCE_CONTINUE;
}
static void
-linklocal6_check_complete(NMDevice *self)
+_dev_ipll6_set_llstate(NMDevice *self, NML3IPv6LLState llstate, const struct in6_addr *lladdr)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMConnection * connection;
- const char * method;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ gboolean changed = FALSE;
+ NMDeviceIPState state;
+ NMDeviceIPState old_state;
+
+ if (!lladdr)
+ lladdr = &nm_ip_addr_zero.addr6;
+
+ if (priv->ipll_data_6.v6.llstate != llstate
+ || !IN6_ARE_ADDR_EQUAL(&priv->ipll_data_6.v6.lladdr, lladdr)) {
+ changed = TRUE;
+ priv->ipll_data_6.v6.llstate = llstate;
+ priv->ipll_data_6.v6.lladdr = *lladdr;
+ }
+
+ nm_assert((priv->ipll_data_6.v6.ipv6ll
+ && NM_IN_SET(priv->ipll_data_6.v6.llstate,
+ NM_L3_IPV6LL_STATE_STARTING,
+ NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS,
+ NM_L3_IPV6LL_STATE_READY,
+ NM_L3_IPV6LL_STATE_DAD_FAILED))
+ || (!priv->ipll_data_6.v6.ipv6ll
+ && NM_IN_SET(priv->ipll_data_6.v6.llstate,
+ NM_L3_IPV6LL_STATE_NONE,
+ NM_L3_IPV6LL_STATE_DEFUNCT)));
+
+ switch (priv->ipll_data_6.v6.llstate) {
+ case NM_L3_IPV6LL_STATE_NONE:
+ state = NM_DEVICE_IP_STATE_NONE;
+ break;
+ case NM_L3_IPV6LL_STATE_DEFUNCT:
+ case NM_L3_IPV6LL_STATE_DAD_FAILED:
+ state = NM_DEVICE_IP_STATE_FAILED;
+ break;
+ case NM_L3_IPV6LL_STATE_READY:
+ state = NM_DEVICE_IP_STATE_READY;
+ break;
+ case NM_L3_IPV6LL_STATE_STARTING:
+ case NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS:
+ state = NM_DEVICE_IP_STATE_PENDING;
+ break;
+ default:
+ state = nm_assert_unreachable_val(NM_DEVICE_IP_STATE_FAILED);
+ break;
+ }
- if (!priv->linklocal6_timeout_id) {
- /* we are not waiting for linklocal to complete. Nothing to do. */
- return;
+ old_state = priv->ipll_data_6.state;
+ if (priv->ipll_data_6.state != state) {
+ priv->ipll_data_6.state = state;
+ changed = TRUE;
}
- if (!priv->ext_ip6_config_captured
- || !nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured),
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) {
- /* we don't have a non-tentative link local address yet. Wait longer. */
- return;
+ if (priv->ipll_data_6.v6.llstate != NM_L3_IPV6LL_STATE_DEFUNCT)
+ nm_clear_g_source_inst(&priv->ipll_data_6.v6.retry_source);
+ else if (!priv->ipll_data_6.v6.retry_source) {
+ /* we schedule a timer to try to recover from this... Possibly some higher layer
+ * will however fail the activation... */
+ priv->ipll_data_6.v6.retry_source =
+ nm_g_timeout_add_source(10000, _dev_ipll6_state_retry_cb, self);
}
- nm_clear_g_source(&priv->linklocal6_timeout_id);
+ if (changed) {
+ char sbuf[NM_UTILS_INET_ADDRSTRLEN];
- connection = nm_device_get_applied_connection(self);
- g_assert(connection);
+ _LOGT_ipll(AF_INET6,
+ "set state %s (was %s, llstate=%s, lladdr=%s)",
+ nm_device_ip_state_to_string(priv->ipll_data_6.state),
+ nm_device_ip_state_to_string(old_state),
+ nm_l3_ipv6ll_state_to_string(priv->ipll_data_6.v6.llstate),
+ nm_ip_addr_is_null(AF_INET6, &priv->ipll_data_6.v6.lladdr)
+ ? "(none)"
+ : _nm_utils_inet6_ntop(&priv->ipll_data_6.v6.lladdr, sbuf));
+ }
- method = nm_device_get_effective_ip_config_method(self, AF_INET6);
+ if (changed)
+ _dev_ip_state_check_async(self, AF_INET6);
- _LOGD(LOGD_DEVICE,
- "linklocal6: waiting for link-local addresses successful, continue with method %s",
- method);
-
- if (NM_IN_STRSET(method,
- NM_SETTING_IP6_CONFIG_METHOD_AUTO,
- NM_SETTING_IP6_CONFIG_METHOD_SHARED))
- addrconf6_start_with_link_ready(self);
- else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
- if (!dhcp6_start_with_link_ready(self, connection)) {
- /* Time out IPv6 instead of failing the entire activation */
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET6);
- }
- } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- else
- g_return_if_fail(FALSE);
+ if (priv->ipll_data_6.v6.llstate == NM_L3_IPV6LL_STATE_READY) {
+ /* if we got an IPv6LL address, we might poke some other methods
+ * to progress... */
+ _dev_ipac6_start_continue(self);
+ _dev_ipdhcpx_start_continue(self, AF_INET6);
+ }
}
static void
-check_and_add_ipv6ll_addr(NMDevice *self)
+_dev_ipll6_state_change_cb(NML3IPv6LL * ipv6ll,
+ NML3IPv6LLState llstate,
+ const struct in6_addr *lladdr,
+ gpointer user_data)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- struct in6_addr lladdr;
- NMConnection * connection;
- NMSettingIP6Config *s_ip6 = NULL;
- GError * error = NULL;
- const char * addr_type;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ _dev_ipll6_set_llstate(user_data, llstate, lladdr);
+}
- if (!priv->ipv6ll_handle)
- return;
+static void
+_dev_ipll6_start(NMDevice *self)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMConnection * connection;
+ NMSettingIP6Config * s_ip6 = NULL;
+ gboolean assume;
+ const char * ifname;
+ NML3IPv6LLState llstate;
+ const struct in6_addr *lladdr;
- if (priv->ext_ip6_config_captured
- && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured),
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) {
- /* Already have an LL address, nothing to do */
+ if (priv->ipll_data_6.v6.ipv6ll)
return;
- }
- priv->ipv6ll_has = FALSE;
- memset(&priv->ipv6ll_addr, 0, sizeof(priv->ipv6ll_addr));
+ if (!priv->l3cfg) {
+ _LOGD(LOGD_IP6, "linklocal6: no IP link for IPv6");
+ goto out_fail;
+ }
- memset(&lladdr, 0, sizeof(lladdr));
- lladdr.s6_addr16[0] = htons(0xfe80);
+ ifname = nm_device_get_ip_iface(self);
+ if (!ifname) {
+ _LOGD(LOGD_IP6, "linklocal6: no interface name for IPv6");
+ goto out_fail;
+ }
connection = nm_device_get_applied_connection(self);
if (connection)
s_ip6 = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(connection));
+ assume = nm_device_sys_iface_state_is_external_or_assume(self);
+
if (s_ip6
&& nm_setting_ip6_config_get_addr_gen_mode(s_ip6)
== NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) {
@@ -10332,73 +10276,31 @@ check_and_add_ipv6ll_addr(NMDevice *self)
const char * stable_id;
stable_id = _prop_get_connection_stable_id(self, connection, &stable_type);
- if (!nm_utils_ipv6_addr_set_stable_privacy_may_fail(stable_type,
- &lladdr,
- nm_device_get_iface(self),
- stable_id,
- priv->linklocal6_dad_counter++,
- &error)) {
- _LOGW(LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message);
- g_clear_error(&error);
- linklocal6_failed(self);
- return;
- }
- addr_type = "stable-privacy";
+ priv->ipll_data_6.v6.ipv6ll = nm_l3_ipv6ll_new_stable_privacy(priv->l3cfg,
+ assume,
+ stable_type,
+ ifname,
+ stable_id,
+ _dev_ipll6_state_change_cb,
+ self);
} else {
NMUtilsIPv6IfaceId iid;
- if (priv->linklocal6_timeout_id) {
- /* We already started and attempt to add a LL address. For the EUI-64
- * mode we can't pick a new one, we'll just fail. */
- _LOGW(LOGD_IP6, "linklocal6: DAD failed for an EUI-64 address");
- linklocal6_failed(self);
- return;
- }
-
if (!nm_device_get_ip_iface_identifier(self, &iid, TRUE)) {
_LOGW(LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue");
- return;
+ goto out_fail;
}
- nm_utils_ipv6_addr_set_interface_identifier(&lladdr, &iid);
- addr_type = "EUI-64";
- }
-
- _LOGD(LOGD_IP6,
- "linklocal6: generated %s IPv6LL address %s",
- addr_type,
- _nm_utils_inet6_ntop(&lladdr, sbuf));
- priv->ipv6ll_has = TRUE;
- priv->ipv6ll_addr = lladdr;
- ip_config_merge_and_apply(self, AF_INET6, TRUE);
-}
-
-static gboolean
-linklocal6_start(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- nm_clear_g_source(&priv->linklocal6_timeout_id);
-
- if (priv->ext_ip6_config_captured
- && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured),
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL))
- return TRUE;
-
- _LOGD(LOGD_DEVICE,
- "linklocal6: starting IPv6 with method '%s', but the device has no link-local addresses "
- "configured. Wait.",
- nm_device_get_effective_ip_config_method(self, AF_INET6));
+ priv->ipll_data_6.v6.ipv6ll =
+ nm_l3_ipv6ll_new_token(priv->l3cfg, assume, &iid, _dev_ipll6_state_change_cb, self);
+ }
- check_and_add_ipv6ll_addr(self);
+ llstate = nm_l3_ipv6ll_get_state(priv->ipll_data_6.v6.ipv6ll, &lladdr);
+ _dev_ipll6_set_llstate(self, llstate, lladdr);
+ return;
- /* Depending on the network and what the 'dad_transmits' and 'retrans_time_ms'
- * sysctl values are, DAD for the IPv6LL address may take quite a while.
- * FIXME: use dad/retrans sysctl values if they are higher than a minimum time.
- * (rh #1101809)
- */
- priv->linklocal6_timeout_id = g_timeout_add_seconds(15, linklocal6_timeout_cb, self);
- return FALSE;
+out_fail:
+ _dev_ipll6_set_llstate(self, NM_L3_IPV6LL_STATE_DEFUNCT, NULL);
}
/*****************************************************************************/
@@ -10561,13 +10463,16 @@ set_platform_mtu(NMDevice *self, guint32 mtu)
}
static void
-_commit_mtu(NMDevice *self, const NMIP4Config *config)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMDeviceMtuSource source = NM_DEVICE_MTU_SOURCE_NONE;
- guint32 ip6_mtu, ip6_mtu_orig;
- guint32 mtu_desired, mtu_desired_orig;
- guint32 mtu_plat;
+_commit_mtu(NMDevice *self)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDeviceMtuSource source = NM_DEVICE_MTU_SOURCE_NONE;
+ const NML3ConfigData *l3cd;
+ guint32 ip6_mtu_orig;
+ guint32 ip6_mtu;
+ guint32 mtu_desired_orig;
+ guint32 mtu_desired;
+ guint32 mtu_plat;
struct {
gboolean initialized;
guint32 value;
@@ -10575,7 +10480,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config)
0,
};
int ifindex;
- char sbuf[64], sbuf1[64], sbuf2[64];
+ char sbuf[64];
+ char sbuf1[64];
+ char sbuf2[64];
gboolean success = TRUE;
ifindex = nm_device_get_ip_ifindex(self);
@@ -10589,8 +10496,11 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config)
return;
}
+ l3cd = nm_l3cfg_get_combined_l3cd(priv->l3cfg, FALSE);
+
{
- guint32 mtu = 0;
+ guint32 mtu = 0;
+ guint32 mtu2;
gboolean force = FALSE;
/* We take the MTU from various sources: (in order of increasing
@@ -10617,9 +10527,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config)
if (NM_DEVICE_GET_CLASS(self)->get_configured_mtu)
mtu = NM_DEVICE_GET_CLASS(self)->get_configured_mtu(self, &source, &force);
- if (config && !force && source < NM_DEVICE_MTU_SOURCE_IP_CONFIG
- && nm_ip4_config_get_mtu(config)) {
- mtu = nm_ip4_config_get_mtu(config);
+ if (l3cd && !force && source < NM_DEVICE_MTU_SOURCE_IP_CONFIG
+ && (mtu2 = nm_l3_config_data_get_mtu(l3cd)) > 0) {
+ mtu = mtu2;
source = NM_DEVICE_MTU_SOURCE_IP_CONFIG;
}
@@ -10808,239 +10718,181 @@ nm_device_commit_mtu(NMDevice *self)
state = nm_device_get_state(self);
if (state >= NM_DEVICE_STATE_CONFIG && state < NM_DEVICE_STATE_DEACTIVATING) {
_LOGT(LOGD_DEVICE, "mtu: commit-mtu...");
- _commit_mtu(self, NM_DEVICE_GET_PRIVATE(self)->ip_config_4);
+ _commit_mtu(self);
} else
_LOGT(LOGD_DEVICE,
"mtu: commit-mtu... skip due to state %s",
nm_device_state_to_string(state));
}
+/*****************************************************************************/
+
static void
-ndisc_config_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, NMDevice *self)
+_dev_ipac6_ndisc_set_router_config(NMDevice *self)
{
- NMNDiscConfigMap changed = changed_int;
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- guint i;
-
- g_return_if_fail(priv->act_request.obj);
-
- if (!applied_config_get_current(&priv->ac_ip6_config))
- applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6);
-
- if (changed & NM_NDISC_CONFIG_ADDRESSES) {
- guint32 ifa_flags;
-
- /* Check, whether kernel is recent enough to help user space handling RA.
- * If it's not supported, we have no ipv6-privacy and must add autoconf
- * addresses as /128. The reason for the /128 is to prevent the kernel
- * from adding a prefix route for this address. */
- ifa_flags = IFA_F_NOPREFIXROUTE;
- if (NM_IN_SET(priv->ndisc_use_tempaddr,
- NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
- NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
- ifa_flags |= IFA_F_MANAGETEMPADDR;
-
- nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.orig,
- rdata->addresses,
- rdata->addresses_n,
- 64,
- ifa_flags);
- if (priv->ac_ip6_config.current) {
- nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.current,
- rdata->addresses,
- rdata->addresses_n,
- 64,
- ifa_flags);
- }
- }
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ const NML3ConfigData *l3cd;
- if (NM_FLAGS_ANY(changed, NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_GATEWAYS)) {
- nm_ip6_config_reset_routes_ndisc((NMIP6Config *) priv->ac_ip6_config.orig,
- rdata->gateways,
- rdata->gateways_n,
- rdata->routes,
- rdata->routes_n,
- nm_device_get_route_table(self, AF_INET6),
- nm_device_get_route_metric(self, AF_INET6));
- if (priv->ac_ip6_config.current) {
- nm_ip6_config_reset_routes_ndisc((NMIP6Config *) priv->ac_ip6_config.current,
- rdata->gateways,
- rdata->gateways_n,
- rdata->routes,
- rdata->routes_n,
- nm_device_get_route_table(self, AF_INET6),
- nm_device_get_route_metric(self, AF_INET6));
- }
- }
+ if (!priv->ipac6_data.ndisc)
+ return;
- if (changed & NM_NDISC_CONFIG_DNS_SERVERS) {
- /* Rebuild DNS server list from neighbor discovery cache. */
- applied_config_reset_nameservers(&priv->ac_ip6_config);
+ if (nm_ndisc_get_node_type(priv->ipac6_data.ndisc) != NM_NDISC_NODE_TYPE_ROUTER)
+ return;
- for (i = 0; i < rdata->dns_servers_n; i++)
- applied_config_add_nameserver(&priv->ac_ip6_config,
- (const NMIPAddr *) &rdata->dns_servers[i].address);
- }
+ /* FIXME(l3cfg): this doesn't seem right. What is the meaning of the l3cd at this
+ * point? Also, when do we need to reset the config (and call this function again?). */
+ l3cd = nm_l3cfg_get_combined_l3cd(priv->l3cfg, FALSE);
+ if (l3cd)
+ nm_ndisc_set_config(priv->ipac6_data.ndisc, l3cd);
+}
- if (changed & NM_NDISC_CONFIG_DNS_DOMAINS) {
- /* Rebuild domain list from neighbor discovery cache. */
- applied_config_reset_searches(&priv->ac_ip6_config);
+static void
+_dev_ipac6_set_state(NMDevice *self, NMDeviceIPState state)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- for (i = 0; i < rdata->dns_domains_n; i++)
- applied_config_add_search(&priv->ac_ip6_config, rdata->dns_domains[i].domain);
+ if (priv->ipac6_data.state != state) {
+ _LOGD_ipac6("set state: %s (was %s)",
+ nm_device_ip_state_to_string(state),
+ nm_device_ip_state_to_string(priv->ipac6_data.state));
+ priv->ipac6_data.state = state;
}
+}
- if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
- dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, TRUE);
-
- priv->dhcp6.mode = rdata->dhcp_level;
- if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE) {
- _LOGD(LOGD_DEVICE | LOGD_DHCP6,
- "Activation: Stage 3 of 5 (IP Configure Start) starting DHCPv6"
- " as requested by IPv6 router...");
- if (!dhcp6_start(self, FALSE)) {
- if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) {
- nm_device_state_changed(self,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_DHCP_START_FAILED);
- return;
- }
- }
- }
- }
+static void
+_dev_ipac6_ndisc_config_changed(NMNDisc * ndisc,
+ const NMNDiscData * rdata,
+ guint changed_i,
+ const NML3ConfigData *l3cd,
+ NMDevice * self)
+{
+ _dev_ipac6_grace_period_start(self, 0, TRUE);
- if (changed & NM_NDISC_CONFIG_HOP_LIMIT)
- nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe(nm_device_get_platform(self),
- nm_device_get_ip_iface(self),
- rdata->hop_limit);
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_AC_6, l3cd, FALSE);
- if (changed & NM_NDISC_CONFIG_REACHABLE_TIME) {
- nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(nm_device_get_platform(self),
- nm_device_get_ip_iface(self),
- rdata->reachable_time_ms);
- }
+ _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_READY);
- if (changed & NM_NDISC_CONFIG_RETRANS_TIMER) {
- nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(nm_device_get_platform(self),
- nm_device_get_ip_iface(self),
- rdata->retrans_timer_ms);
- }
+ _dev_ipdhcp6_set_dhcp_level(self, rdata->dhcp_level);
- if (changed & NM_NDISC_CONFIG_MTU) {
- if (priv->ip6_mtu != rdata->mtu) {
- _LOGD(LOGD_DEVICE, "mtu: set IPv6 MTU to %u", (guint) rdata->mtu);
- priv->ip6_mtu = rdata->mtu;
- }
- }
+ _dev_l3_cfg_commit(self, FALSE);
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
+ _dev_ip_state_check_async(self, AF_INET6);
}
static void
-ndisc_ra_timeout(NMNDisc *ndisc, NMDevice *self)
+_dev_ipac6_handle_timeout(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- /* We don't want to stop listening for router advertisements completely,
- * but instead let device activation continue activating. If an RA
- * shows up later, we'll use it as long as the device is not disconnected.
- */
+ _LOGD_ipac6("timeout for autoconf (IPv6 router advertisement) reached");
- _LOGD(LOGD_IP6, "timed out waiting for IPv6 router advertisement");
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) {
- /* If RA is our only source of addressing information and we don't
- * ever receive one, then time out IPv6. But if there is other
- * IPv6 configuration, like manual IPv6 addresses or external IPv6
- * config, consider that sufficient for IPv6 success.
- *
- * FIXME: it doesn't seem correct to determine this based on which
- * addresses we find inside priv->ip_config_6.
- */
- if (priv->ip_config_6
- && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ip_config_6),
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY))
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- else
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET6);
- }
+ nm_clear_g_source_inst(&priv->ipac6_data.ndisc_grace_source);
+
+ _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_FAILED);
+
+ _dev_ip_state_check_async(self, AF_INET6);
}
static void
-addrconf6_start_with_link_ready(NMDevice *self)
+_dev_ipac6_ndisc_ra_timeout(NMNDisc *ndisc, NMDevice *self)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMUtilsIPv6IfaceId iid;
+ _dev_ipac6_handle_timeout(self);
+}
- g_assert(priv->ndisc);
+static gboolean
+_dev_ipac6_grace_period_expired(gpointer user_data)
+{
+ _dev_ipac6_handle_timeout(user_data);
+ return G_SOURCE_REMOVE;
+}
- if (nm_device_get_ip_iface_identifier(self, &iid, FALSE)) {
- _LOGD(LOGD_IP6, "addrconf6: using the device EUI-64 identifier");
- nm_ndisc_set_iid(priv->ndisc, iid);
- } else {
- /* Don't abort the addrconf at this point -- if ndisc needs the iid
- * it will notice this itself. */
- _LOGI(LOGD_IP6, "addrconf6: no interface identifier; IPv6 address creation may fail");
+static gboolean
+_dev_ipac6_grace_period_start(NMDevice *self, guint32 timeout_sec, gboolean force_restart)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ gboolean stopped;
+
+ /* In any other case (expired lease, assumed connection, etc.),
+ * wait for some time before failing the IP method.
+ */
+ if (!force_restart && priv->ipac6_data.ndisc_grace_source) {
+ /* already pending. */
+ return FALSE;
}
- /* Apply any manual configuration before starting RA */
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "failed to apply manual IPv6 configuration");
+ /* Start a grace period equal to the RA timeout multiplied
+ * by a constant factor. */
+
+ stopped = nm_clear_g_source_inst(&priv->ipac6_data.ndisc_grace_source);
- if (nm_ndisc_get_node_type(priv->ndisc) == NM_NDISC_NODE_TYPE_ROUTER) {
- nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "1");
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- priv->needs_ip6_subnet = TRUE;
- g_signal_emit(self, signals[IP6_SUBNET_NEEDED], 0);
+ if (timeout_sec == 0) {
+ if (stopped)
+ _LOGD_ipac6("grace period stopped");
+ return FALSE;
}
- priv->ndisc_changed_id = g_signal_connect(priv->ndisc,
- NM_NDISC_CONFIG_RECEIVED,
- G_CALLBACK(ndisc_config_changed),
- self);
- priv->ndisc_timeout_id = g_signal_connect(priv->ndisc,
- NM_NDISC_RA_TIMEOUT_SIGNAL,
- G_CALLBACK(ndisc_ra_timeout),
- self);
+ nm_assert(timeout_sec <= G_MAXINT32);
- ndisc_set_router_config(priv->ndisc, self);
- nm_ndisc_start(priv->ndisc);
- priv->ndisc_started = TRUE;
- return;
+ if (timeout_sec >= G_MAXUINT / (GRACE_PERIOD_MULTIPLIER * 1000u))
+ timeout_sec = NM_RA_TIMEOUT_INFINITY;
+
+ if (timeout_sec == NM_RA_TIMEOUT_INFINITY) {
+ _LOGD_ipac6("grace period starts with infinity timeout");
+ priv->ipac6_data.ndisc_grace_source = g_source_ref(nm_g_source_sentinel_get(0));
+ } else {
+ _LOGD_ipac6("grace period starts with %u seconds", timeout_sec);
+ priv->ipac6_data.ndisc_grace_source =
+ nm_g_timeout_add_source(timeout_sec * (GRACE_PERIOD_MULTIPLIER * 1000u),
+ _dev_ipac6_grace_period_expired,
+ self);
+ }
+
+ return TRUE;
}
-static gboolean
-addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
+static void
+_dev_ipac6_start(NMDevice *self)
{
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
NMConnection * connection;
- NMSettingIP6Config *s_ip6 = NULL;
- GError * error = NULL;
+ NMSettingIP6Config *s_ip = NULL;
+ NMNDiscNodeType node_type;
NMUtilsStableType stable_type;
const char * stable_id;
- NMNDiscNodeType node_type;
int max_addresses;
int router_solicitations;
int router_solicitation_interval;
guint32 ra_timeout;
guint32 default_ra_timeout;
+ NMUtilsIPv6IfaceId iid;
- if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) {
- _LOGI(LOGD_IP6, "addrconf6: kernel does not support IPv6");
- return FALSE;
+ if (priv->ipac6_data.state == NM_DEVICE_IP_STATE_NONE) {
+ if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) {
+ _LOGI_ipac6("addrconf6: kernel does not support IPv6");
+ _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_FAILED);
+ _dev_ip_state_check_async(self, AF_INET6);
+ return;
+ }
+
+ _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_PENDING);
}
- connection = nm_device_get_applied_connection(self);
- g_assert(connection);
+ if (NM_IN_SET(priv->ipll_data_6.state, NM_DEVICE_IP_STATE_NONE, NM_DEVICE_IP_STATE_PENDING)) {
+ _dev_ipac6_grace_period_start(self, 30, TRUE);
+ _dev_ipll6_start(self);
+ return;
+ }
- nm_assert(!applied_config_get_current(&priv->ac_ip6_config));
- applied_config_clear(&priv->ac_ip6_config);
+ if (priv->ipac6_data.ndisc) {
+ /* we already started. Nothing to do. */
+ return;
+ }
- nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref);
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
+ connection = nm_device_get_applied_connection(self);
+ if (connection)
+ s_ip = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(connection));
- s_ip6 = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(connection));
- g_assert(s_ip6);
+ g_return_if_fail(s_ip);
if (nm_streq(nm_device_get_effective_ip_config_method(self, AF_INET6),
NM_SETTING_IP6_CONFIG_METHOD_SHARED))
@@ -11063,60 +10915,95 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
ra_timeout = default_ra_timeout;
}
- stable_id = _prop_get_connection_stable_id(self, connection, &stable_type);
- priv->ndisc = nm_lndp_ndisc_new(nm_device_get_platform(self),
- nm_device_get_ip_ifindex(self),
- nm_device_get_ip_iface(self),
- stable_type,
- stable_id,
- nm_setting_ip6_config_get_addr_gen_mode(s_ip6),
- node_type,
- max_addresses,
- router_solicitations,
- router_solicitation_interval,
- ra_timeout,
- &error);
- if (!priv->ndisc) {
- _LOGE(LOGD_IP6, "addrconf6: failed to start neighbor discovery: %s", error->message);
- g_error_free(error);
- return FALSE;
+ stable_id = _prop_get_connection_stable_id(self, connection, &stable_type);
+
+ {
+ const NMNDiscConfig config = {
+ .l3cfg = nm_device_get_l3cfg(self),
+ .ifname = nm_device_get_ip_iface(self),
+ .stable_type = stable_type,
+ .network_id = stable_id,
+ .addr_gen_mode = nm_setting_ip6_config_get_addr_gen_mode(s_ip),
+ .node_type = node_type,
+ .max_addresses = max_addresses,
+ .router_solicitations = router_solicitations,
+ .router_solicitation_interval = router_solicitation_interval,
+ .ra_timeout = ra_timeout,
+ .ip6_privacy = _prop_get_ipv6_ip6_privacy(self),
+ };
+
+ priv->ipac6_data.ndisc = nm_lndp_ndisc_new(&config);
+
+ priv->ipac6_data.ndisc_changed_id =
+ g_signal_connect(priv->ipac6_data.ndisc,
+ NM_NDISC_CONFIG_RECEIVED,
+ G_CALLBACK(_dev_ipac6_ndisc_config_changed),
+ self);
+ priv->ipac6_data.ndisc_timeout_id =
+ g_signal_connect(priv->ipac6_data.ndisc,
+ NM_NDISC_RA_TIMEOUT_SIGNAL,
+ G_CALLBACK(_dev_ipac6_ndisc_ra_timeout),
+ self);
}
- priv->ndisc_use_tempaddr = use_tempaddr;
+ if (nm_device_get_ip_iface_identifier(self, &iid, FALSE)) {
+ _LOGD_ipac6("using the device EUI-64 identifier");
+ nm_ndisc_set_iid(priv->ipac6_data.ndisc, iid);
+ } else {
+ /* Don't abort the addrconf at this point -- if ndisc needs the iid
+ * it will notice this itself. */
+ _LOGD_ipac6("no interface identifier; IPv6 address creation may fail");
+ }
- /* ensure link local is ready... */
- if (!linklocal6_start(self)) {
- /* wait for the LL address to show up */
- return TRUE;
+ if (nm_ndisc_get_node_type(priv->ipac6_data.ndisc) == NM_NDISC_NODE_TYPE_ROUTER) {
+ nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "1");
+ priv->needs_ip6_subnet = TRUE;
+ g_signal_emit(self, signals[IP6_SUBNET_NEEDED], 0);
}
- /* already have the LL address; kick off neighbor discovery */
- addrconf6_start_with_link_ready(self);
- return TRUE;
+ _dev_ipac6_ndisc_set_router_config(self);
+
+ if (node_type == NM_NDISC_NODE_TYPE_ROUTER)
+ _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_READY);
+ else
+ _dev_ipac6_grace_period_start(self, ra_timeout, TRUE);
+
+ nm_ndisc_start(priv->ipac6_data.ndisc);
}
static void
-addrconf6_cleanup(NMDevice *self)
+_dev_ipac6_start_continue(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- priv->ndisc_started = FALSE;
- nm_clear_g_signal_handler(priv->ndisc, &priv->ndisc_changed_id);
- nm_clear_g_signal_handler(priv->ndisc, &priv->ndisc_timeout_id);
+ if (priv->ipac6_data.state != NM_DEVICE_IP_STATE_NONE)
+ _dev_ipac6_start(self);
+}
+
+static void
+_dev_ipac6_cleanup(NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- applied_config_clear(&priv->ac_ip6_config);
- nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref);
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
- if (priv->ndisc) {
- nm_ndisc_stop(priv->ndisc);
- g_clear_object(&priv->ndisc);
+ nm_clear_g_source_inst(&priv->ipac6_data.ndisc_grace_source);
+
+ nm_clear_g_signal_handler(priv->ipac6_data.ndisc, &priv->ipac6_data.ndisc_changed_id);
+ nm_clear_g_signal_handler(priv->ipac6_data.ndisc, &priv->ipac6_data.ndisc_timeout_id);
+
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_AC_6, NULL, FALSE);
+
+ if (priv->ipac6_data.ndisc) {
+ nm_ndisc_stop(priv->ipac6_data.ndisc);
+ g_clear_object(&priv->ipac6_data.ndisc);
}
+
+ _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_NONE);
}
/*****************************************************************************/
static void
-save_ip6_properties(NMDevice *self)
+_dev_sysctl_save_ip6_properties(NMDevice *self)
{
static const char *const ip6_properties_to_save[] = {
"accept_ra",
@@ -11149,61 +11036,80 @@ save_ip6_properties(NMDevice *self)
}
static void
-restore_ip6_properties(NMDevice *self)
+_dev_sysctl_restore_ip6_properties(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
GHashTableIter iter;
- gpointer key, value;
+ gpointer key;
+ gpointer value;
g_hash_table_iter_init(&iter, priv->ip6_saved_properties);
- while (g_hash_table_iter_next(&iter, &key, &value)) {
- /* Don't touch "disable_ipv6" if we're doing userland IPv6LL */
- if (priv->ipv6ll_handle && nm_streq(key, "disable_ipv6"))
- continue;
+ while (g_hash_table_iter_next(&iter, &key, &value))
nm_device_sysctl_ip_conf_set(self, AF_INET6, key, value);
- }
}
static void
-set_disable_ipv6(NMDevice *self, const char *value)
+_dev_sysctl_set_disable_ipv6(NMDevice *self, gboolean do_disable)
{
- /* We only touch disable_ipv6 when NM is not managing the IPv6LL address */
- if (!NM_DEVICE_GET_PRIVATE(self)->ipv6ll_handle)
- nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", value);
+ nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", do_disable ? "1" : "0");
}
+/*****************************************************************************/
+
static void
-set_nm_ipv6ll(NMDevice *self, gboolean enable)
+_dev_addrgenmode6_set(NMDevice *self, guint8 addr_gen_mode)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- int ifindex = nm_device_get_ip_ifindex(self);
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ int ifindex = nm_device_get_ip_ifindex(self);
+ const NMPlatformLink *plink;
+ int r;
+ int cur_addr_gen_mode;
+ char sbuf[100];
- priv->ipv6ll_handle = enable;
- if (ifindex > 0) {
- int r;
-
- _LOGD(LOGD_IP6, "will %s userland IPv6LL", enable ? "enable" : "disable");
- r = nm_platform_link_set_inet6_addr_gen_mode(nm_device_get_platform(self),
- ifindex,
- enable ? NM_IN6_ADDR_GEN_MODE_NONE
- : NM_IN6_ADDR_GEN_MODE_EUI64);
- if (r < 0) {
- _NMLOG(NM_IN_SET(r, -NME_PL_NOT_FOUND, -NME_PL_OPNOTSUPP) ? LOGL_DEBUG : LOGL_WARN,
- LOGD_IP6,
- "failed to %s userspace IPv6LL address handling (%s)",
- enable ? "enable" : "disable",
- nm_strerror(r));
- }
+ if (ifindex <= 0)
+ return;
- if (enable) {
- gs_free char *value = NULL;
+ plink = nm_platform_link_get(nm_device_get_platform(self), ifindex);
+ if (!plink)
+ return;
- /* Bounce IPv6 to ensure the kernel stops IPv6LL address generation */
- value = nm_device_sysctl_ip_conf_get(self, AF_INET6, "disable_ipv6");
- if (nm_streq0(value, "0"))
- nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1");
+ cur_addr_gen_mode = _nm_platform_link_get_inet6_addr_gen_mode(plink);
+ nm_assert(cur_addr_gen_mode >= 0 && cur_addr_gen_mode <= 255);
+
+ if (!priv->addrgenmode6_data.previous_mode_has) {
+ priv->addrgenmode6_data.previous_mode_has = TRUE;
+ priv->addrgenmode6_data.previous_mode_val = cur_addr_gen_mode;
+ nm_assert(priv->addrgenmode6_data.previous_mode_val == cur_addr_gen_mode);
+ }
+
+ _LOGD_ip(AF_INET6,
+ "addrgenmode6: set %s%s",
+ nm_platform_link_inet6_addrgenmode2str(addr_gen_mode, sbuf, sizeof(sbuf)),
+ (cur_addr_gen_mode == addr_gen_mode) ? " (already set)" : "");
+
+ if (cur_addr_gen_mode == addr_gen_mode)
+ return;
+
+ r = nm_platform_link_set_inet6_addr_gen_mode(nm_device_get_platform(self),
+ ifindex,
+ addr_gen_mode);
+ if (r < 0) {
+ _NMLOG_ip(NM_IN_SET(r, -NME_PL_NOT_FOUND, -NME_PL_OPNOTSUPP) ? LOGL_DEBUG : LOGL_WARN,
+ AF_INET6,
+ "addrgenmode6: failed to set %s: (%s)",
+ nm_platform_link_inet6_addrgenmode2str(addr_gen_mode, sbuf, sizeof(sbuf)),
+ nm_strerror(r));
+ }
- /* Ensure IPv6 is enabled */
+ if (addr_gen_mode == NM_IN6_ADDR_GEN_MODE_NONE) {
+ gs_free char *value = NULL;
+
+ /* Bounce IPv6 to ensure the kernel stops IPv6LL address generation */
+ _LOGD_ip(AF_INET6,
+ "addrgenmode6: toggle disable_ipv6 sysctl after disabling addr-gen-mode");
+ value = nm_device_sysctl_ip_conf_get(self, AF_INET6, "disable_ipv6");
+ if (nm_streq0(value, "0")) {
+ nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1");
nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "0");
}
}
@@ -11229,30 +11135,44 @@ ip_requires_slaves(NMDevice *self, int addr_family)
NM_SETTING_IP6_CONFIG_METHOD_DHCP);
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * self,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family)
{
const int IS_IPv4 = NM_IS_IPv4(addr_family);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDeviceClass * klass = NM_DEVICE_GET_CLASS(self);
NMConnection * connection;
- NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
+ int ip_ifindex;
const char * method;
- nm_assert_addr_family(addr_family);
+ if (nm_device_sys_iface_state_is_external(self))
+ goto out;
connection = nm_device_get_applied_connection(self);
+ g_return_if_fail(connection);
- g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
+ ip_ifindex = nm_device_get_ip_ifindex(self);
+
+ if (ip_ifindex >= 0 && !nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex)
+ && !nm_device_sys_iface_state_is_external(self)) {
+ nm_platform_link_change_flags(nm_device_get_platform(self), ip_ifindex, IFF_UP, TRUE);
+ if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex))
+ _LOGW(LOGD_DEVICE,
+ "interface %s not up for IP configuration",
+ nm_device_get_ip_iface(self));
+ }
if (connection_ip_method_requires_carrier(connection, addr_family, NULL)
&& nm_device_is_master(self) && !priv->carrier) {
- _LOGI(LOGD_IP | LOGD_DEVICE,
- "IPv%c config waiting until carrier is on",
- nm_utils_addr_family_to_char(addr_family));
- return NM_ACT_STAGE_RETURN_IP_WAIT;
+ if (!priv->ip_data_x[IS_IPv4].wait_for_carrier) {
+ _LOGT_ip(addr_family, "waiting until carrier is on");
+ priv->ip_data_x[IS_IPv4].wait_for_carrier = TRUE;
+ }
+ goto out;
+ }
+ if (priv->ip_data_x[IS_IPv4].wait_for_carrier) {
+ _LOGT_ip(addr_family, "waiting until carrier completed");
+ priv->ip_data_x[IS_IPv4].wait_for_carrier = FALSE;
}
if (nm_device_is_master(self) && ip_requires_slaves(self, addr_family)) {
@@ -11260,93 +11180,46 @@ act_stage3_ip_config_start(NMDevice * self,
* a successful IP configuration attempt, then postpone IP addressing.
*/
if (!have_any_ready_slaves(self)) {
- _LOGI(LOGD_DEVICE | LOGD_IP,
- "IPv%c config waiting until slaves are ready",
- nm_utils_addr_family_to_char(addr_family));
- return NM_ACT_STAGE_RETURN_IP_WAIT;
+ if (!priv->ip_data_x[IS_IPv4].wait_for_ports) {
+ _LOGT_ip(addr_family, "waiting for ports");
+ priv->ip_data_x[IS_IPv4].wait_for_ports = TRUE;
+ }
+ goto out;
}
}
-
- if (!IS_IPv4)
- priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE;
+ if (priv->ip_data_x[IS_IPv4].wait_for_ports) {
+ _LOGT_ip(addr_family, "waiting until ports completed");
+ priv->ip_data_x[IS_IPv4].wait_for_ports = FALSE;
+ }
method = nm_device_get_effective_ip_config_method(self, addr_family);
- _LOGD(LOGD_IP | LOGD_DEVICE,
- "IPv%c config method is %s",
- nm_utils_addr_family_to_char(addr_family),
- method);
+ _dev_ipmanual_start(self);
if (IS_IPv4) {
- if (NM_IN_STRSET(method,
- NM_SETTING_IP4_CONFIG_METHOD_AUTO,
- NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
- NMSettingIPConfig *s_ip4;
- NMIP4Config ** configs, *config;
- guint num_addresses;
-
- s_ip4 = nm_connection_get_setting_ip4_config(connection);
- g_return_val_if_fail(s_ip4, NM_ACT_STAGE_RETURN_FAILURE);
- num_addresses = nm_setting_ip_config_get_num_addresses(s_ip4);
-
- if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
- ret = dhcp4_start(self);
- if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_DHCP_START_FAILED);
- return ret;
- }
- } else {
- g_return_val_if_fail(num_addresses != 0, NM_ACT_STAGE_RETURN_FAILURE);
- ret = NM_ACT_STAGE_RETURN_POSTPONE;
- }
-
- if (num_addresses) {
- config = nm_device_ip4_config_new(self);
- nm_ip4_config_merge_setting(config,
- nm_connection_get_setting_ip4_config(connection),
- NM_SETTING_CONNECTION_MDNS_DEFAULT,
- NM_SETTING_CONNECTION_LLMNR_DEFAULT,
- nm_device_get_route_table(self, AF_INET),
- nm_device_get_route_metric(self, AF_INET));
- configs = g_new0(NMIP4Config *, 2);
- configs[0] = config;
- ipv4_dad_start(self, configs, ipv4_manual_method_apply);
- }
- } else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
- ret = ipv4ll_start(self);
- if (ret == NM_ACT_STAGE_RETURN_FAILURE)
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED);
- } else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
- if (out_config) {
- *out_config = shared4_new_config(self, connection);
- if (*out_config) {
- priv->dnsmasq_manager = nm_dnsmasq_manager_new(nm_device_get_ip_iface(self));
- ret = NM_ACT_STAGE_RETURN_SUCCESS;
- } else {
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- ret = NM_ACT_STAGE_RETURN_FAILURE;
- }
- } else
- g_return_val_if_reached(NM_ACT_STAGE_RETURN_FAILURE);
- } else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED))
- ret = NM_ACT_STAGE_RETURN_SUCCESS;
- else
- _LOGW(LOGD_IP4, "unhandled IPv4 config method '%s'; will fail", method);
-
- return ret;
- } else {
- NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
- const char * ip6_privacy_str = "0";
- NMPlatform * platform;
- int ifindex;
+ if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO))
+ _dev_ipdhcpx_start(self, AF_INET);
+ else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
+ _dev_ipll4_start(self);
+ else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
+ _dev_ipshared4_start(self);
+ else if (NM_IN_STRSET(method,
+ NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
+ NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
+ /* pass */
+ } else
+ nm_assert_not_reached();
+ }
+ if (!IS_IPv4) {
if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) {
- nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1");
- return NM_ACT_STAGE_RETURN_IP_DONE;
- }
-
- if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
- if (!nm_device_sys_iface_state_is_external(self)) {
+ if (!priv->ip_data_x[IS_IPv4].is_disabled) {
+ priv->ip_data_x[IS_IPv4].is_disabled = TRUE;
+ nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1");
+ }
+ } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
+ if (!priv->ip_data_x[IS_IPv4].is_ignore) {
+ priv->ip_data_x[IS_IPv4].is_ignore = TRUE;
if (priv->master) {
/* If a device only has an IPv6 link-local address,
* we don't generate an assumed connection. Therefore,
@@ -11356,165 +11229,62 @@ act_stage3_ip_config_start(NMDevice * self,
* slave should not depend on the previous state. Flush
* addresses and routes on activation.
*/
- ifindex = nm_device_get_ip_ifindex(self);
- platform = nm_device_get_platform(self);
-
- if (ifindex > 0) {
- gs_unref_object NMIP6Config *config = nm_device_ip6_config_new(self);
-
- nm_platform_ip_route_flush(platform, AF_INET6, ifindex);
- nm_platform_ip_address_flush(platform, AF_INET6, ifindex);
- nm_device_set_ip_config(self, AF_INET6, (NMIPConfig *) config, FALSE, NULL);
+ if (ip_ifindex > 0) {
+ nm_platform_ip_route_flush(nm_device_get_platform(self),
+ AF_INET6,
+ ip_ifindex);
+ nm_platform_ip_address_flush(nm_device_get_platform(self),
+ AF_INET6,
+ ip_ifindex);
}
} else {
- gboolean ipv6ll_handle_old = priv->ipv6ll_handle;
-
/* When activating an IPv6 'ignore' connection we need to revert back
* to kernel IPv6LL, but the kernel won't actually assign an address
* to the interface until disable_ipv6 is bounced.
*/
- set_nm_ipv6ll(self, FALSE);
- if (ipv6ll_handle_old)
- nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1");
- restore_ip6_properties(self);
+ _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_EUI64);
+ _dev_sysctl_set_disable_ipv6(self, TRUE);
+ _dev_sysctl_restore_ip6_properties(self);
}
}
- return NM_ACT_STAGE_RETURN_IP_DONE;
- }
-
- /* Ensure the MTU makes sense. If it was below 1280 the kernel would not
- * expose any ipv6 sysctls or allow presence of any addresses on the interface,
- * including LL, which * would make it impossible to autoconfigure MTU to a
- * correct value. */
- _commit_mtu(self, priv->ip_config_4);
-
- /* Any method past this point requires an IPv6LL address. Use NM-controlled
- * IPv6LL if this is not an assumed connection, since assumed connections
- * will already have IPv6 set up.
- */
- if (!nm_device_sys_iface_state_is_external_or_assume(self))
- set_nm_ipv6ll(self, TRUE);
-
- /* Re-enable IPv6 on the interface */
- nm_device_sysctl_ip_conf_set(self, AF_INET6, "accept_ra", "0");
- set_disable_ipv6(self, "0");
-
- /* Synchronize external IPv6 configuration with kernel, since
- * linklocal6_start() uses the information there to determine if we can
- * proceed with the selected method (SLAAC, DHCP, link-local).
- */
- nm_platform_process_events(nm_device_get_platform(self));
- g_clear_object(&priv->ext_ip6_config_captured);
- priv->ext_ip6_config_captured =
- nm_ip6_config_capture(nm_device_get_multi_index(self),
- nm_device_get_platform(self),
- nm_device_get_ip_ifindex(self),
- NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
-
- ip6_privacy = _prop_get_ipv6_ip6_privacy(self);
-
- if (NM_IN_STRSET(method,
- NM_SETTING_IP6_CONFIG_METHOD_AUTO,
- NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
- if (!addrconf6_start(self, ip6_privacy)) {
- /* IPv6 might be disabled; allow IPv4 to proceed */
- ret = NM_ACT_STAGE_RETURN_IP_FAIL;
- } else
- ret = NM_ACT_STAGE_RETURN_POSTPONE;
- } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
- ret =
- linklocal6_start(self) ? NM_ACT_STAGE_RETURN_SUCCESS : NM_ACT_STAGE_RETURN_POSTPONE;
- } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
- priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_MANAGED;
- if (!dhcp6_start(self, TRUE)) {
- /* IPv6 might be disabled; allow IPv4 to proceed */
- ret = NM_ACT_STAGE_RETURN_IP_FAIL;
+ } else {
+ /* Ensure the MTU makes sense. If it was below 1280 the kernel would not
+ * expose any ipv6 sysctls or allow presence of any addresses on the interface,
+ * including LL, which * would make it impossible to autoconfigure MTU to a
+ * correct value. */
+ _commit_mtu(self);
+
+ /* Any method past this point requires an IPv6LL address. Use NM-controlled
+ * IPv6LL if this is not an assumed connection, since assumed connections
+ * will already have IPv6 set up.
+ */
+ _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_NONE);
+
+ /* Re-enable IPv6 on the interface */
+ nm_device_sysctl_ip_conf_set(self, AF_INET6, "accept_ra", "0");
+ _dev_sysctl_set_disable_ipv6(self, FALSE);
+
+ if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
+ _dev_ipll6_start(self);
+ else if (NM_IN_STRSET(method, NM_SETTING_IP6_CONFIG_METHOD_AUTO))
+ _dev_ipac6_start(self);
+ else if (NM_IN_STRSET(method, NM_SETTING_IP6_CONFIG_METHOD_SHARED))
+ _dev_ipshared6_start(self);
+ else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
+ priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_MANAGED;
+ _dev_ipdhcpx_start(self, AF_INET6);
+ } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+ /* pass */
} else
- ret = NM_ACT_STAGE_RETURN_POSTPONE;
- } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL))
- ret = NM_ACT_STAGE_RETURN_SUCCESS;
- else
- _LOGW(LOGD_IP6, "unhandled IPv6 config method '%s'; will fail", method);
-
- if (ret != NM_ACT_STAGE_RETURN_FAILURE
- && !nm_device_sys_iface_state_is_external_or_assume(self)) {
- switch (ip6_privacy) {
- case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN:
- case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
- ip6_privacy_str = "0";
- break;
- case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
- ip6_privacy_str = "1";
- break;
- case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
- ip6_privacy_str = "2";
- break;
- }
- nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", ip6_privacy_str);
+ nm_assert_not_reached();
}
-
- return ret;
}
-}
-gboolean
-nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family)
-{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMActStageReturn ret;
- NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
- gs_unref_object NMIPConfig *ip_config = NULL;
-
- g_assert(priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_WAIT);
+ if (klass->act_stage3_ip_config)
+ klass->act_stage3_ip_config(self, addr_family);
- if (nm_device_sys_iface_state_is_external(self)) {
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE);
- check_ip_state(self, FALSE, TRUE);
- return TRUE;
- }
-
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_CONF);
-
- ret = NM_DEVICE_GET_CLASS(self)->act_stage3_ip_config_start(self,
- addr_family,
- (gpointer *) &ip_config,
- &failure_reason);
-
- switch (ret) {
- case NM_ACT_STAGE_RETURN_SUCCESS:
- if (!IS_IPv4) {
- /* Here we get a static IPv6 config, like for Shared where it's
- * autogenerated or from modems where it comes from ModemManager.
- */
- if (!ip_config)
- ip_config = nm_device_ip_config_new(self, addr_family);
- nm_assert(!applied_config_get_current(&priv->ac_ip6_config));
- applied_config_init(&priv->ac_ip6_config, ip_config);
- ip_config = NULL;
- }
- nm_device_activate_schedule_ip_config_result(self, addr_family, ip_config);
- break;
- case NM_ACT_STAGE_RETURN_IP_DONE:
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE);
- check_ip_state(self, FALSE, TRUE);
- break;
- case NM_ACT_STAGE_RETURN_FAILURE:
- nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, failure_reason);
- return FALSE;
- case NM_ACT_STAGE_RETURN_IP_FAIL:
- /* Activation not wanted */
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_FAIL);
- break;
- case NM_ACT_STAGE_RETURN_IP_WAIT:
- /* Wait for something to try IP config again */
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_WAIT);
- break;
- default:
- g_assert(ret == NM_ACT_STAGE_RETURN_POSTPONE);
- }
-
- return TRUE;
+out:
+ _dev_ip_state_check_async(self, addr_family);
}
static void
@@ -11541,12 +11311,12 @@ fw_change_zone_cb(NMFirewalldManager * firewalld_manager,
switch (priv->fw_state) {
case FIREWALL_STATE_WAIT_STAGE_3:
priv->fw_state = FIREWALL_STATE_INITIALIZED;
- nm_device_activate_schedule_stage3_ip_config_start(self);
+ nm_device_activate_schedule_stage3_ip_config(self, TRUE);
break;
case FIREWALL_STATE_WAIT_IP_CONFIG:
priv->fw_state = FIREWALL_STATE_INITIALIZED;
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE
- || priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE)
+ if (priv->ip_data_4.state == NM_DEVICE_IP_STATE_READY
+ || priv->ip_data_6.state == NM_DEVICE_IP_STATE_READY)
nm_device_start_ip_check(self);
break;
case FIREWALL_STATE_INITIALIZED:
@@ -11598,24 +11368,48 @@ fw_change_zone(NMDevice *self)
self);
}
-/*
- * activate_stage3_ip_config_start
- *
- * Begin automatic/manual IP configuration
- *
- */
static void
-activate_stage3_ip_config_start(NMDevice *self)
+activate_stage3_ip_config(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
int ifindex;
+ /* stage3 is different from stage1+2.
+ *
+ * What is true in all cases is that when we start a stage, we call the corresponding
+ * nm_device_activate_schedule_stage*() function. But usually the stage cannot complete
+ * right away but needs to wait for some things to happen. So the activate_stage*() function
+ * returns, and will be later proceeded by calling *the same* stage again. That means,
+ * activate_stage*() must be re-entrant and be called repeatedly until we can proceed
+ * to the next stage. Only when the stage is completed, we schedule the next one.
+ *
+ * stage3 is different. It does IP configuration and as such (the stage handling itself)
+ * cannot fail. If a failure happens (for example for DHCP), we remember that (in priv->ipdhcp_data_x)
+ * and issue _dev_ip_state_check_async(). That one combines the DHCP state to determine the
+ * overall per-address-family state (priv->ip_data_x). Those states are then combined
+ * further into priv->combinedip_state, which then leads to nm_device_state_changed()
+ * (which for example can make the device fully ACTIVATED or FAILED).
+ *
+ * The difference between stage1+2 and stage3 is that IP configuration is running continuously
+ * while the device is active. As such the activate_stage3_ip_config() does not fail directly,
+ * unlike the other stages which can abort via NM_ACT_STAGE_RETURN_FAILURE. */
+
g_return_if_fail(priv->act_request.obj);
ifindex = nm_device_get_ip_ifindex(self);
+ if (priv->ip_data_4.do_reapply) {
+ _LOGD_ip(AF_INET, "reapply...");
+ _cleanup_ip_pre(self, AF_INET, CLEANUP_TYPE_DECONFIGURE);
+ }
+ if (priv->ip_data_6.do_reapply) {
+ _LOGD_ip(AF_INET6, "reapply...");
+ _cleanup_ip_pre(self, AF_INET6, CLEANUP_TYPE_DECONFIGURE);
+ }
+
/* Add the interface to the specified firewall zone */
- if (priv->fw_state == FIREWALL_STATE_UNMANAGED) {
+ switch (priv->fw_state) {
+ case FIREWALL_STATE_UNMANAGED:
if (nm_device_sys_iface_state_is_external(self)) {
/* fake success */
priv->fw_state = FIREWALL_STATE_INITIALIZED;
@@ -11625,143 +11419,140 @@ activate_stage3_ip_config_start(NMDevice *self)
return;
}
/* no ifindex, nothing to do for now */
- } else if (priv->fw_state == FIREWALL_STATE_WAIT_STAGE_3) {
+ break;
+ case FIREWALL_STATE_WAIT_STAGE_3:
/* a firewall call for stage3 is pending. Return and wait. */
return;
+ default:
+ nm_assert(NM_IN_SET((FirewallState) priv->fw_state,
+ FIREWALL_STATE_INITIALIZED,
+ FIREWALL_STATE_WAIT_IP_CONFIG));
+ break;
}
-
nm_assert(ifindex <= 0 || priv->fw_state == FIREWALL_STATE_INITIALIZED);
- _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_WAIT);
- _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_WAIT);
-
- _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_LAYER2_READY);
-
- nm_device_state_changed(self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
-
- /* Device should be up before we can do anything with it */
- if (!nm_device_sys_iface_state_is_external(self)
- && (ifindex = nm_device_get_ip_ifindex(self)) > 0
- && !nm_platform_link_is_up(nm_device_get_platform(self), ifindex))
- _LOGW(LOGD_DEVICE,
- "interface %s not up for IP configuration",
- nm_device_get_ip_iface(self));
+ if (priv->state < NM_DEVICE_STATE_IP_CONFIG) {
+ _dev_ip_state_req_timeout_schedule(self, AF_INET);
+ _dev_ip_state_req_timeout_schedule(self, AF_INET6);
- if (nm_device_activate_ip4_state_in_wait(self)
- && !nm_device_activate_stage3_ip_start(self, AF_INET))
- return;
+ _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_LAYER2_READY);
- if (nm_device_activate_ip6_state_in_wait(self)
- && !nm_device_activate_stage3_ip_start(self, AF_INET6))
- return;
+ nm_device_state_changed(self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
- /* Proxy */
- nm_device_set_proxy_config(self, NULL);
+ /* Device should be up before we can do anything with it */
+ if (!nm_device_sys_iface_state_is_external(self) && ifindex > 0
+ && !nm_platform_link_is_up(nm_device_get_platform(self), ifindex))
+ _LOGW(LOGD_DEVICE,
+ "interface %s not up for IP configuration",
+ nm_device_get_ip_iface(self));
+ }
- check_ip_state(self, TRUE, TRUE);
+ activate_stage3_ip_config_for_addr_family(self, AF_INET);
+ activate_stage3_ip_config_for_addr_family(self, AF_INET6);
}
-/*
- * nm_device_activate_schedule_stage3_ip_config_start
- *
- * Schedule IP configuration start
- */
void
-nm_device_activate_schedule_stage3_ip_config_start(NMDevice *self)
+nm_device_activate_schedule_stage3_ip_config(NMDevice *self, gboolean do_sync)
{
- NMDevicePrivate *priv;
-
- g_return_if_fail(NM_IS_DEVICE(self));
-
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- g_return_if_fail(priv->act_request.obj);
-
- activation_source_schedule(self, activate_stage3_ip_config_start, AF_INET);
+ activation_source_invoke_or_schedule(self, activate_stage3_ip_config, do_sync);
}
-static NMActStageReturn
-act_stage4_ip_config_timeout(NMDevice * self,
- int addr_family,
- NMDeviceStateReason *out_failure_reason)
+/*****************************************************************************/
+
+static void
+_dev_ipsharedx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state)
{
- nm_assert_addr_family(addr_family);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- if (!get_ip_config_may_fail(self, addr_family)) {
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- return NM_ACT_STAGE_RETURN_FAILURE;
+ if (priv->ipshared_data_x[IS_IPv4].state != state) {
+ _LOGD_ipshared(addr_family,
+ "set state %s (was %s)",
+ nm_device_ip_state_to_string(state),
+ nm_device_ip_state_to_string(priv->ipshared_data_x[IS_IPv4].state));
+ priv->ipshared_data_x[IS_IPv4].state = state;
}
-
- return NM_ACT_STAGE_RETURN_SUCCESS;
}
static void
-activate_stage4_ip_config_timeout_x(NMDevice *self, int addr_family)
+_dev_ipsharedx_cleanup(NMDevice *self, int addr_family)
{
- NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
- NMActStageReturn ret;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- ret =
- NM_DEVICE_GET_CLASS(self)->act_stage4_ip_config_timeout(self, addr_family, &failure_reason);
+ if (IS_IPv4) {
+ if (priv->ipshared_data_4.v4.dnsmasq_manager) {
+ nm_clear_g_signal_handler(priv->ipshared_data_4.v4.dnsmasq_manager,
+ &priv->ipshared_data_4.v4.dnsmasq_state_id);
+ nm_dnsmasq_manager_stop(priv->ipshared_data_4.v4.dnsmasq_manager);
+ g_clear_object(&priv->ipshared_data_4.v4.dnsmasq_manager);
+ }
- if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
- return;
+ if (priv->ipshared_data_4.v4.firewall_config) {
+ nm_firewall_config_apply(priv->ipshared_data_4.v4.firewall_config, FALSE);
+ nm_clear_pointer(&priv->ipshared_data_4.v4.firewall_config, nm_firewall_config_free);
+ }
- if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
- nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, failure_reason);
- return;
+ nm_clear_pointer(&priv->ipshared_data_4.v4.shared_ip_handle, nm_netns_shared_ip_release);
}
- g_assert(ret == NM_ACT_STAGE_RETURN_SUCCESS);
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_FAIL);
- check_ip_state(self, FALSE, TRUE);
+ _dev_ipsharedx_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE);
}
-static void
-activate_stage4_ip_config_timeout_4(NMDevice *self)
-{
- activate_stage4_ip_config_timeout_x(self, AF_INET);
-}
+/*****************************************************************************/
-static void
-activate_stage4_ip_config_timeout_6(NMDevice *self)
+static const NML3ConfigData *
+_dev_ipshared4_new_l3cd(NMDevice *self, NMConnection *connection, NMPlatformIP4Address *out_addr4)
{
- activate_stage4_ip_config_timeout_x(self, AF_INET6);
-}
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMSettingIPConfig * s_ip4;
+ NMPlatformIP4Address address = {
+ .addr_source = NM_IP_CONFIG_SOURCE_SHARED,
+ };
-#define activate_stage4_ip_config_timeout_x_fcn(addr_family) \
- (NM_IS_IPv4(addr_family) ? activate_stage4_ip_config_timeout_4 \
- : activate_stage4_ip_config_timeout_6)
+ g_return_val_if_fail(self, NULL);
+ g_return_val_if_fail(connection, NULL);
-void
-nm_device_activate_schedule_ip_config_timeout(NMDevice *self, int addr_family)
-{
- NMDevicePrivate *priv;
+ s_ip4 = nm_connection_get_setting_ip4_config(connection);
+ if (s_ip4 && nm_setting_ip_config_get_num_addresses(s_ip4) > 0) {
+ /* Use the first user-supplied address */
+ NMIPAddress *user = nm_setting_ip_config_get_address(s_ip4, 0);
+ in_addr_t a;
- g_return_if_fail(NM_IS_DEVICE(self));
+ nm_ip_address_get_address_binary(user, &a);
+ nm_platform_ip4_address_set_addr(&address, a, nm_ip_address_get_prefix(user));
+ nm_clear_pointer(&priv->ipshared_data_4.v4.shared_ip_handle, nm_netns_shared_ip_release);
+ } else {
+ if (!priv->ipshared_data_4.v4.shared_ip_handle)
+ priv->ipshared_data_4.v4.shared_ip_handle =
+ nm_netns_shared_ip_reserve(nm_device_get_netns(self));
+ nm_platform_ip4_address_set_addr(&address,
+ priv->ipshared_data_4.v4.shared_ip_handle->addr,
+ 24);
+ }
- priv = NM_DEVICE_GET_PRIVATE(self);
+ l3cd = nm_device_create_l3_config_data(self, NM_IP_CONFIG_SOURCE_SHARED);
+ nm_l3_config_data_add_address_4(l3cd, &address);
- g_return_if_fail(priv->act_request.obj);
+ NM_SET_OUT(out_addr4, address);
- activation_source_schedule(self,
- activate_stage4_ip_config_timeout_x_fcn(addr_family),
- addr_family);
+ return nm_l3_config_data_seal(g_steal_pointer(&l3cd));
}
static gboolean
-share_init(NMDevice *self, GError **error)
-{
- const char *const modules[] = {"ip_tables",
- "iptable_nat",
- "nf_nat_ftp",
- "nf_nat_irc",
- "nf_nat_sip",
- "nf_nat_tftp",
- "nf_nat_pptp",
- "nf_nat_h323"};
- guint i;
- int errsv;
+_dev_ipshared4_init(NMDevice *self)
+{
+ static const char *const modules[] = {"ip_tables",
+ "iptable_nat",
+ "nf_nat_ftp",
+ "nf_nat_irc",
+ "nf_nat_sip",
+ "nf_nat_tftp",
+ "nf_nat_pptp",
+ "nf_nat_h323"};
+ int errsv;
+ guint i;
if (nm_platform_sysctl_get_int32(nm_device_get_platform(self),
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"),
@@ -11772,15 +11563,7 @@ share_init(NMDevice *self, GError **error)
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"),
"1")) {
errsv = errno;
- _LOGD(LOGD_SHARING,
- "share: error enabling IPv4 forwarding: (%d) %s",
- errsv,
- nm_strerror_native(errsv));
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- "cannot set ipv4/ip_forward: %s",
- nm_strerror_native(errsv));
+ _LOGW_ipshared(AF_INET, "error enabling IPv4 forwarding: %s", nm_strerror_native(errsv));
return FALSE;
}
@@ -11793,10 +11576,9 @@ share_init(NMDevice *self, GError **error)
NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_dynaddr"),
"1")) {
errsv = errno;
- _LOGD(LOGD_SHARING,
- "share: error enabling dynamic addresses: (%d) %s",
- errsv,
- nm_strerror_native(errsv));
+ _LOGD_ipshared(AF_INET,
+ "share: error enabling dynamic addresses: %s",
+ nm_strerror_native(errsv));
}
for (i = 0; i < G_N_ELEMENTS(modules); i++)
@@ -11805,48 +11587,59 @@ share_init(NMDevice *self, GError **error)
return TRUE;
}
-static gboolean
-start_sharing(NMDevice *self, NMIP4Config *config, GError **error)
+static void
+_dev_ipshared4_dnsmasq_state_changed_cb(NMDnsMasqManager *manager, guint status, gpointer user_data)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMActRequest * req;
- const NMPlatformIP4Address *ip4_addr = NULL;
- const char * ip_iface;
- GError * local = NULL;
- NMConnection * conn;
- NMSettingConnection * s_con;
- gboolean announce_android_metered;
- NMFirewallConfig * firewall_config;
+ NMDevice *self = NM_DEVICE(user_data);
- g_return_val_if_fail(config, FALSE);
+ if (status != NM_DNSMASQ_STATUS_DEAD)
+ return;
+
+ _dev_ipsharedx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_FAILED);
+ _dev_ip_state_check_async(self, AF_INET);
+}
+
+static void
+_dev_ipshared4_start(NMDevice *self)
+{
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ NMPlatformIP4Address ip4_addr;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ const char * ip_iface;
+ gs_free_error GError *error = NULL;
+ NMSettingConnection * s_con;
+ gboolean announce_android_metered;
+ NMConnection * applied;
+
+ if (priv->ipshared_data_4.state != NM_DEVICE_IP_STATE_NONE)
+ return;
+
+ nm_assert(!priv->ipshared_data_4.v4.firewall_config);
+ nm_assert(!priv->ipshared_data_4.v4.dnsmasq_manager);
+ nm_assert(priv->ipshared_data_4.v4.dnsmasq_state_id == 0);
ip_iface = nm_device_get_ip_iface(self);
- if (!ip_iface) {
- g_set_error(error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "device has no ip interface");
- return FALSE;
- }
+ g_return_if_fail(ip_iface);
- ip4_addr = nm_ip4_config_get_first_address(config);
- if (!ip4_addr || !ip4_addr->address) {
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- "could not determine IPv4 address");
- return FALSE;
- }
+ applied = nm_device_get_applied_connection(self);
+ g_return_if_fail(applied);
- if (!share_init(self, error))
- return FALSE;
+ _dev_ipsharedx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_PENDING);
- req = nm_device_get_act_request(self);
- g_return_val_if_fail(req, FALSE);
+ l3cd = _dev_ipshared4_new_l3cd(self, applied, &ip4_addr);
+ if (!l3cd) {
+ nm_assert_not_reached();
+ goto out_fail;
+ }
- firewall_config = nm_firewall_config_new(ip_iface, ip4_addr->address, ip4_addr->plen);
+ if (!_dev_ipshared4_init(self))
+ goto out_fail;
- nm_act_request_set_shared(req, firewall_config);
+ priv->ipshared_data_4.v4.firewall_config =
+ nm_firewall_config_new(ip_iface, ip4_addr.address, ip4_addr.plen);
+ nm_firewall_config_apply(priv->ipshared_data_4.v4.firewall_config, TRUE);
- conn = nm_act_request_get_applied_connection(req);
- s_con = nm_connection_get_setting_connection(conn);
+ s_con = nm_connection_get_setting_connection(applied);
switch (nm_setting_connection_get_metered(s_con)) {
case NM_METERED_YES:
@@ -11868,353 +11661,55 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error)
break;
}
- if (!nm_dnsmasq_manager_start(priv->dnsmasq_manager,
- config,
+ priv->ipshared_data_4.v4.dnsmasq_manager = nm_dnsmasq_manager_new(ip_iface);
+
+ if (!nm_dnsmasq_manager_start(priv->ipshared_data_4.v4.dnsmasq_manager,
+ l3cd,
announce_android_metered,
- &local)) {
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- "could not start dnsmasq due to %s",
- local->message);
- g_error_free(local);
- nm_act_request_set_shared(req, NULL);
- return FALSE;
+ &error)) {
+ _LOGW_ipshared(AF_INET, "could not start dnsmasq: %s", error->message);
+ goto out_fail;
}
- priv->dnsmasq_state_id = g_signal_connect(priv->dnsmasq_manager,
- NM_DNS_MASQ_MANAGER_STATE_CHANGED,
- G_CALLBACK(dnsmasq_state_changed_cb),
- self);
- return TRUE;
-}
+ priv->ipshared_data_4.v4.dnsmasq_state_id =
+ g_signal_connect(priv->ipshared_data_4.v4.dnsmasq_manager,
+ NM_DNS_MASQ_MANAGER_STATE_CHANGED,
+ G_CALLBACK(_dev_ipshared4_dnsmasq_state_changed_cb),
+ self);
-static void
-arp_cleanup(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_SHARED_4, l3cd, FALSE);
+ _dev_ip_state_check_async(self, AF_INET);
+ return;
- nm_clear_pointer(&priv->acd.announcing, nm_acd_manager_free);
+out_fail:
+ _dev_ipsharedx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_FAILED);
+ _dev_ip_state_check_async(self, AF_INET);
}
-void
-nm_device_arp_announce(NMDevice *self)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMConnection * connection;
- NMSettingIPConfig *s_ip4;
- guint num, i;
- const guint8 * hw_addr;
- size_t hw_addr_len = 0;
-
- arp_cleanup(self);
-
- hw_addr = nm_platform_link_get_address(nm_device_get_platform(self),
- nm_device_get_ip_ifindex(self),
- &hw_addr_len);
-
- if (!hw_addr || hw_addr_len != ETH_ALEN)
- return;
-
- /* We only care about manually-configured addresses; DHCP- and autoip-configured
- * ones should already have been seen on the network at this point.
- */
- connection = nm_device_get_applied_connection(self);
- if (!connection)
- return;
- s_ip4 = nm_connection_get_setting_ip4_config(connection);
- if (!s_ip4)
- return;
- num = nm_setting_ip_config_get_num_addresses(s_ip4);
- if (num == 0)
- return;
-
- priv->acd.announcing =
- nm_acd_manager_new(nm_device_get_ip_ifindex(self), hw_addr, hw_addr_len, NULL, NULL);
-
- for (i = 0; i < num; i++) {
- NMIPAddress *ip = nm_setting_ip_config_get_address(s_ip4, i);
- in_addr_t addr;
-
- if (inet_pton(AF_INET, nm_ip_address_get_address(ip), &addr) == 1)
- nm_acd_manager_add_address(priv->acd.announcing, addr);
- else
- g_warn_if_reached();
- }
-
- nm_acd_manager_announce_addresses(priv->acd.announcing);
-}
+/*****************************************************************************/
static void
-activate_stage5_ip_config_result_x(NMDevice *self, int addr_family)
+_dev_ipshared6_start(NMDevice *self)
{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMActRequest * req;
- const char * method;
- int ip_ifindex;
- int errsv;
-
- req = nm_device_get_act_request(self);
- g_assert(req);
-
- nm_clear_g_source_inst(&priv->ip_req_timeout_source_x[IS_IPv4]);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- /* Interface must be IFF_UP before IP config can be applied */
- ip_ifindex = nm_device_get_ip_ifindex(self);
- g_return_if_fail(ip_ifindex);
+ _dev_ipac6_start(self);
- if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex)
- && !nm_device_sys_iface_state_is_external(self)) {
- nm_platform_link_change_flags(nm_device_get_platform(self), ip_ifindex, IFF_UP, TRUE);
- if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex))
- _LOGW(LOGD_DEVICE,
- "interface %s not up for IP configuration",
- nm_device_get_ip_iface(self));
- }
-
- if (!ip_config_merge_and_apply(self, addr_family, TRUE)) {
- _LOGD(LOGD_DEVICE | LOGD_IPX(IS_IPv4),
- "Activation: Stage 5 of 5 (IPv%c Commit) failed",
- nm_utils_addr_family_to_char(addr_family));
- nm_device_ip_method_failed(self, addr_family, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
+ if (priv->ipshared_data_6.state != NM_DEVICE_IP_STATE_NONE)
return;
- }
-
- if (!IS_IPv4) {
- if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE
- && priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) {
- if (applied_config_get_current(&priv->dhcp6.ip6_config)) {
- /* If IPv6 wasn't the first IP to complete, and DHCP was used,
- * then ensure dispatcher scripts get the DHCP lease information.
- */
- nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_6,
- self,
- NULL,
- NULL,
- NULL,
- NULL);
- } else {
- /* still waiting for first dhcp6 lease. */
- return;
- }
- }
- }
-
- /* Start IPv4 sharing/IPv6 forwarding if we need it */
- method = nm_device_get_effective_ip_config_method(self, addr_family);
- if (IS_IPv4) {
- if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
- gs_free_error GError *error = NULL;
-
- if (!start_sharing(self, priv->ip_config_4, &error)) {
- _LOGW(LOGD_SHARING,
- "Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed: %s",
- error->message);
- nm_device_ip_method_failed(self,
- AF_INET,
- NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
- return;
- }
- }
- } else {
- if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
- if (!nm_platform_sysctl_set(
- nm_device_get_platform(self),
- NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv6/conf/all/forwarding"),
- "1")) {
- errsv = errno;
- _LOGE(LOGD_SHARING,
- "share: error enabling IPv6 forwarding: (%d) %s",
- errsv,
- nm_strerror_native(errsv));
- nm_device_ip_method_failed(self,
- AF_INET6,
- NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
- return;
- }
- }
- }
-
- if (IS_IPv4) {
- if (priv->dhcp_data_4.client) {
- gs_free_error GError *error = NULL;
-
- if (!nm_dhcp_client_accept(priv->dhcp_data_4.client, &error)) {
- _LOGW(LOGD_DHCP4,
- "Activation: Stage 5 of 5 (IPv4 Commit) error accepting lease: %s",
- error->message);
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_DHCP_ERROR);
- return;
- }
- }
-
- /* If IPv4 wasn't the first to complete, and DHCP was used, then ensure
- * dispatcher scripts get the DHCP lease information.
- */
- if (priv->dhcp_data_4.client && nm_device_activate_ip4_state_in_conf(self)
- && (nm_device_get_state(self) > NM_DEVICE_STATE_IP_CONFIG)) {
- nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_4,
- self,
- NULL,
- NULL,
- NULL,
- NULL);
- }
- }
-
- if (!IS_IPv4) {
- /* Check if we have to wait for DAD */
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF && !priv->dad6_ip6_config) {
- if (!priv->carrier && priv->ignore_carrier && get_ip_config_may_fail(self, AF_INET6))
- _LOGI(LOGD_DEVICE | LOGD_IP6,
- "IPv6 DAD: carrier missing and ignored, not delaying activation");
- else
- priv->dad6_ip6_config = dad6_get_pending_addresses(self);
-
- if (priv->dad6_ip6_config) {
- _LOGD(LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: awaiting termination");
- } else {
- _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_DONE);
- check_ip_state(self, FALSE, TRUE);
- }
- }
- }
-
- if (IS_IPv4 && priv->carrier) {
- /* We send ARP announcements only when the link gets carrier,
- * otherwise the announcements would be lost. Furthermore, for
- * controllers having carrier implies that there is at least one
- * port and therefore the MAC address is the correct one.
- */
- nm_device_arp_announce(self);
- }
-
- if (IS_IPv4) {
- /* Enter the IP_CHECK state if this is the first method to complete */
- _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_DONE);
- check_ip_state(self, FALSE, TRUE);
- }
-}
-
-static void
-activate_stage5_ip_config_result_4(NMDevice *self)
-{
- activate_stage5_ip_config_result_x(self, AF_INET);
-}
-
-static void
-activate_stage5_ip_config_result_6(NMDevice *self)
-{
- activate_stage5_ip_config_result_x(self, AF_INET6);
-}
-
-#define activate_stage5_ip_config_result_x_fcn(addr_family) \
- (NM_IS_IPv4(addr_family) ? activate_stage5_ip_config_result_4 \
- : activate_stage5_ip_config_result_6)
-
-void
-nm_device_activate_schedule_ip_config_result(NMDevice *self, int addr_family, NMIPConfig *config)
-{
- NMDevicePrivate *priv;
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
-
- g_return_if_fail(NM_IS_DEVICE(self));
- g_return_if_fail(!config || (IS_IPv4 && nm_ip_config_get_addr_family(config) == AF_INET));
-
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- if (IS_IPv4) {
- applied_config_init(&priv->dev_ip_config_4, config);
- } else {
- /* If IP had previously failed, move it back to NM_DEVICE_IP_STATE_CONF since we
- * clearly now have configuration.
- */
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL)
- _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_CONF);
- }
-
- activation_source_schedule(self,
- activate_stage5_ip_config_result_x_fcn(addr_family),
- addr_family);
-}
-
-NMDeviceIPState
-nm_device_activate_get_ip_state(NMDevice *self, int addr_family)
-{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
-
- g_return_val_if_fail(NM_IS_DEVICE(self), NM_DEVICE_IP_STATE_NONE);
- g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), NM_DEVICE_IP_STATE_NONE);
-
- return NM_DEVICE_GET_PRIVATE(self)->ip_state_x[IS_IPv4];
-}
-
-static void
-dad6_add_pending_address(NMDevice * self,
- NMPlatform * platform,
- int ifindex,
- const struct in6_addr *address,
- NMIP6Config ** dad6_config)
-{
- const NMPlatformIP6Address *pl_addr;
-
- pl_addr = nm_platform_ip6_address_get(platform, ifindex, address);
- if (pl_addr && NM_FLAGS_HAS(pl_addr->n_ifa_flags, IFA_F_TENTATIVE)
- && !NM_FLAGS_HAS(pl_addr->n_ifa_flags, IFA_F_DADFAILED)
- && !NM_FLAGS_HAS(pl_addr->n_ifa_flags, IFA_F_OPTIMISTIC)) {
- _LOGt(LOGD_DEVICE,
- "IPv6 DAD: pending address %s",
- nm_platform_ip6_address_to_string(pl_addr, NULL, 0));
-
- if (!*dad6_config)
- *dad6_config = nm_device_ip6_config_new(self);
-
- nm_ip6_config_add_address(*dad6_config, pl_addr);
- }
-}
-
-/*
- * Returns a NMIP6Config containing NM-configured addresses which
- * have the tentative flag, or NULL if none is present.
- */
-static NMIP6Config *
-dad6_get_pending_addresses(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMIP6Config * confs[] = {(NMIP6Config *) applied_config_get_current(&priv->ac_ip6_config),
- (NMIP6Config *) applied_config_get_current(&priv->dhcp6.ip6_config),
- priv->con_ip_config_6,
- (NMIP6Config *) applied_config_get_current(&priv->dev2_ip_config_6)};
- const NMPlatformIP6Address *addr;
- NMIP6Config * dad6_config = NULL;
- NMDedupMultiIter ipconf_iter;
- guint i;
- int ifindex;
- NMPlatform * platform;
-
- ifindex = nm_device_get_ip_ifindex(self);
- g_return_val_if_fail(ifindex > 0, NULL);
-
- platform = nm_device_get_platform(self);
-
- if (priv->ipv6ll_has) {
- dad6_add_pending_address(self, platform, ifindex, &priv->ipv6ll_addr, &dad6_config);
- }
- /* We are interested only in addresses that we have explicitly configured,
- * not in externally added ones.
- */
- for (i = 0; i < G_N_ELEMENTS(confs); i++) {
- if (!confs[i])
- continue;
-
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, confs[i], &addr) {
- dad6_add_pending_address(self, platform, ifindex, &addr->address, &dad6_config);
- }
+ if (!nm_platform_sysctl_set(
+ nm_device_get_platform(self),
+ NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv6/conf/all/forwarding"),
+ "1")) {
+ _LOGW_ipshared(AF_INET6, "failure to enable ipv6 forwarding");
+ _dev_ipsharedx_set_state(self, AF_INET6, NM_DEVICE_IP_STATE_FAILED);
+ _dev_ip_state_check_async(self, AF_INET6);
+ return;
}
- return dad6_config;
+ _dev_ipsharedx_set_state(self, AF_INET6, NM_DEVICE_IP_STATE_READY);
+ _dev_ip_state_check_async(self, AF_INET6);
}
/*****************************************************************************/
@@ -12255,21 +11750,6 @@ act_request_set(NMDevice *self, NMActRequest *act_request)
}
}
-static void
-dnsmasq_cleanup(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- if (!priv->dnsmasq_manager)
- return;
-
- nm_clear_g_signal_handler(priv->dnsmasq_manager, &priv->dnsmasq_state_id);
-
- nm_dnsmasq_manager_stop(priv->dnsmasq_manager);
- g_object_unref(priv->dnsmasq_manager);
- priv->dnsmasq_manager = NULL;
-}
-
gboolean
nm_device_is_nm_owned(NMDevice *self)
{
@@ -12356,32 +11836,23 @@ delete_on_deactivate_check_and_schedule(NMDevice *self)
static void
_cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_NONE);
+ _dev_ipsharedx_cleanup(self, addr_family);
- if (nm_clear_g_source(&priv->queued_ip_config_id_x[IS_IPv4])) {
- _LOGD(LOGD_DEVICE,
- "clearing queued IP%c config change",
- nm_utils_addr_family_to_char(addr_family));
- }
+ _dev_ipdev_cleanup(self, addr_family);
- if (IS_IPv4) {
- dhcp4_cleanup(self, cleanup_type, FALSE);
- arp_cleanup(self);
- dnsmasq_cleanup(self);
- ipv4ll_cleanup(self);
- g_slist_free_full(priv->acd.dad_list, (GDestroyNotify) nm_acd_manager_free);
- priv->acd.dad_list = NULL;
- } else {
- g_slist_free_full(priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref);
- priv->dad6_failed_addrs = NULL;
- g_clear_object(&priv->dad6_ip6_config);
- dhcp6_cleanup(self, cleanup_type, FALSE);
- nm_clear_g_source(&priv->linklocal6_timeout_id);
- addrconf6_cleanup(self);
- }
+ _dev_ipdhcpx_cleanup(self, addr_family, TRUE, FALSE);
+
+ if (!IS_IPv4)
+ _dev_ipac6_cleanup(self);
+
+ _dev_ipllx_cleanup(self, addr_family);
+
+ _dev_ipmanual_cleanup(self);
+
+ _dev_ip_state_cleanup(self, AF_UNSPEC);
+ _dev_ip_state_cleanup(self, addr_family);
}
gboolean
@@ -12452,127 +11923,6 @@ _nm_device_hash_check_invalid_keys(GHashTable * hash,
return FALSE;
}
-void
-nm_device_reactivate_ip_config(NMDevice * self,
- int addr_family,
- NMSettingIPConfig *s_ip_old,
- NMSettingIPConfig *s_ip_new)
-{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMDevicePrivate *priv;
- const char * method_old;
- const char * method_new;
-
- g_return_if_fail(NM_IS_DEVICE(self));
-
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- if (priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_NONE)
- return;
-
- g_clear_object(&priv->con_ip_config_x[IS_IPv4]);
- g_clear_object(&priv->ext_ip_config_x[IS_IPv4]);
- if (IS_IPv4) {
- g_clear_object(&priv->dev_ip_config_4.current);
- } else {
- g_clear_object(&priv->ac_ip6_config.current);
- g_clear_object(&priv->dhcp6.ip6_config.current);
- }
- g_clear_object(&priv->dev2_ip_config_x[IS_IPv4].current);
-
- if (!IS_IPv4) {
- if (priv->ipv6ll_handle && !IN6_IS_ADDR_UNSPECIFIED(&priv->ipv6ll_addr))
- priv->ipv6ll_has = TRUE;
- }
-
- priv->con_ip_config_x[IS_IPv4] = nm_device_ip_config_new(self, addr_family);
-
- if (IS_IPv4) {
- nm_ip4_config_merge_setting(priv->con_ip_config_4,
- s_ip_new,
- _prop_get_connection_mdns(self),
- _prop_get_connection_llmnr(self),
- nm_device_get_route_table(self, AF_INET),
- nm_device_get_route_metric(self, AF_INET));
- } else {
- nm_ip6_config_merge_setting(priv->con_ip_config_6,
- s_ip_new,
- nm_device_get_route_table(self, AF_INET6),
- nm_device_get_route_metric(self, AF_INET6));
- }
-
- method_old = (s_ip_old ? nm_setting_ip_config_get_method(s_ip_old) : NULL)
- ?: (IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_DISABLED
- : NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
- method_new = (s_ip_new ? nm_setting_ip_config_get_method(s_ip_new) : NULL)
- ?: (IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_DISABLED
- : NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
-
- if (!nm_streq0(method_old, method_new)) {
- _cleanup_ip_pre(self, addr_family, CLEANUP_TYPE_DECONFIGURE);
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_WAIT);
- if (!nm_device_activate_stage3_ip_start(self, addr_family)) {
- _LOGW(LOGD_IP4,
- "Failed to apply IPv%c configuration",
- nm_utils_addr_family_to_char(addr_family));
- }
- return;
- }
-
- if (s_ip_old && s_ip_new) {
- gint64 metric_old, metric_new;
-
- /* For dynamic IP methods (DHCP, IPv4LL, WWAN) the route metric is
- * set at activation/renewal time using the value from static
- * configuration. To support runtime change we need to update the
- * dynamic configuration in place and tell the DHCP client the new
- * value to use for future renewals.
- */
- metric_old = nm_setting_ip_config_get_route_metric(s_ip_old);
- metric_new = nm_setting_ip_config_get_route_metric(s_ip_new);
-
- if (metric_old != metric_new) {
- if (IS_IPv4) {
- if (priv->dev_ip_config_4.orig) {
- nm_ip4_config_update_routes_metric((NMIP4Config *) priv->dev_ip_config_4.orig,
- nm_device_get_route_metric(self, AF_INET));
- }
- if (priv->dev2_ip_config_4.orig) {
- nm_ip4_config_update_routes_metric((NMIP4Config *) priv->dev2_ip_config_4.orig,
- nm_device_get_route_metric(self, AF_INET));
- }
- if (priv->dhcp_data_4.client) {
- nm_dhcp_client_set_route_metric(priv->dhcp_data_4.client,
- nm_device_get_route_metric(self, AF_INET));
- }
- } else {
- if (priv->ac_ip6_config.orig) {
- nm_ip6_config_update_routes_metric((NMIP6Config *) priv->ac_ip6_config.orig,
- nm_device_get_route_metric(self, AF_INET6));
- }
- if (priv->dhcp6.ip6_config.orig) {
- nm_ip6_config_update_routes_metric((NMIP6Config *) priv->dhcp6.ip6_config.orig,
- nm_device_get_route_metric(self, AF_INET6));
- }
- if (priv->dev2_ip_config_6.orig) {
- nm_ip6_config_update_routes_metric((NMIP6Config *) priv->dev2_ip_config_6.orig,
- nm_device_get_route_metric(self, AF_INET6));
- }
- if (priv->dhcp_data_6.client) {
- nm_dhcp_client_set_route_metric(priv->dhcp_data_6.client,
- nm_device_get_route_metric(self, AF_INET6));
- }
- }
- }
- }
-
- if (nm_device_get_ip_ifindex(self) > 0 && !ip_config_merge_and_apply(self, addr_family, TRUE)) {
- _LOGW(LOGD_IPX(IS_IPv4),
- "Failed to reapply IPv%c configuration",
- nm_utils_addr_family_to_char(addr_family));
- }
-}
-
static void
_pacrunner_manager_add(NMDevice *self)
{
@@ -12581,10 +11931,8 @@ _pacrunner_manager_add(NMDevice *self)
nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id);
priv->pacrunner_conf_id = nm_pacrunner_manager_add(nm_pacrunner_manager_get(),
- priv->proxy_config,
nm_device_get_ip_iface(self),
- NULL,
- NULL);
+ nm_device_get_l3cd(self, TRUE));
}
static void
@@ -12592,12 +11940,12 @@ reactivate_proxy_config(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (!priv->pacrunner_conf_id)
- return;
- nm_device_set_proxy_config(self, priv->dhcp4.pac_url);
- _pacrunner_manager_add(self);
+ if (priv->pacrunner_conf_id)
+ _pacrunner_manager_add(self);
}
+/*****************************************************************************/
+
static gboolean
can_reapply_change(NMDevice * self,
const char *setting_name,
@@ -12692,9 +12040,8 @@ check_and_reapply_connection(NMDevice * self,
NMConnection * applied = nm_device_get_applied_connection(self);
gs_unref_object NMConnection *applied_clone = NULL;
gs_unref_hashtable GHashTable *diffs = NULL;
- NMConnection * con_old, *con_new;
- NMSettingIPConfig * s_ip4_old, *s_ip4_new;
- NMSettingIPConfig * s_ip6_old, *s_ip6_new;
+ NMConnection * con_old;
+ NMConnection * con_new;
GHashTableIter iter;
if (priv->state < NM_DEVICE_STATE_PREPARE || priv->state > NM_DEVICE_STATE_ACTIVATED) {
@@ -12743,11 +12090,11 @@ check_and_reapply_connection(NMDevice * self,
&& version_id
!= nm_active_connection_version_id_get(
(NMActiveConnection *) priv->act_request.obj)) {
- g_set_error_literal(
- error,
- NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_VERSION_ID_MISMATCH,
- "Reapply failed because device changed in the meantime and the version-id mismatches");
+ g_set_error_literal(error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_VERSION_ID_MISMATCH,
+ "Reapply failed because device changed in the meantime and the "
+ "version-id mismatches");
return FALSE;
}
@@ -12810,11 +12157,9 @@ check_and_reapply_connection(NMDevice * self,
} else
con_old = con_new = applied;
- priv->v4_commit_first_time = TRUE;
- priv->v6_commit_first_time = TRUE;
-
priv->v4_route_table_initialized = FALSE;
priv->v6_route_table_initialized = FALSE;
+ priv->l3config_merge_flags_has = FALSE;
/**************************************************************************
* Reapply changes
@@ -12831,20 +12176,21 @@ check_and_reapply_connection(NMDevice * self,
lldp_setup(self, NM_TERNARY_DEFAULT);
if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) {
- s_ip4_old = nm_connection_get_setting_ip4_config(con_old);
- s_ip4_new = nm_connection_get_setting_ip4_config(con_new);
- s_ip6_old = nm_connection_get_setting_ip6_config(con_old);
- s_ip6_new = nm_connection_get_setting_ip6_config(con_new);
-
/* Allow reapply of MTU */
priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE;
- nm_device_reactivate_ip_config(self, AF_INET, s_ip4_old, s_ip4_new);
- nm_device_reactivate_ip_config(self, AF_INET6, s_ip6_old, s_ip6_new);
+ if (nm_g_hash_table_lookup(diffs, NM_SETTING_IP4_CONFIG_SETTING_NAME))
+ priv->ip_data_4.do_reapply = TRUE;
+ if (nm_g_hash_table_lookup(diffs, NM_SETTING_IP6_CONFIG_SETTING_NAME))
+ priv->ip_data_6.do_reapply = TRUE;
+
+ nm_device_activate_schedule_stage3_ip_config(self, FALSE);
_routing_rules_sync(self, NM_TERNARY_TRUE);
reactivate_proxy_config(self);
+
+ nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_REAPPLY, FALSE);
}
if (priv->state >= NM_DEVICE_STATE_IP_CHECK)
@@ -13074,96 +12420,6 @@ impl_device_get_applied_connection(NMDBusObject * obj,
/*****************************************************************************/
-typedef struct {
- gint64 timestamp_ms;
- bool dirty;
-} IP6RoutesTemporaryNotAvailableData;
-
-static gboolean
-_rt6_temporary_not_available_timeout(gpointer user_data)
-{
- NMDevice * self = NM_DEVICE(user_data);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- priv->rt6_temporary_not_available_id = 0;
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
-
- return G_SOURCE_REMOVE;
-}
-
-static gboolean
-_rt6_temporary_not_available_set(NMDevice *self, GPtrArray *temporary_not_available)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- IP6RoutesTemporaryNotAvailableData *data;
- GHashTableIter iter;
- gint64 now_ms, oldest_ms;
- const gint64 MAX_AGE_MS = 20000;
- guint i;
- gboolean success = TRUE;
-
- if (!temporary_not_available || !temporary_not_available->len) {
- /* nothing outstanding. Clear tracking the routes. */
- nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref);
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
- return success;
- }
-
- if (priv->rt6_temporary_not_available) {
- g_hash_table_iter_init(&iter, priv->rt6_temporary_not_available);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &data))
- data->dirty = TRUE;
- } else {
- priv->rt6_temporary_not_available =
- g_hash_table_new_full((GHashFunc) nmp_object_id_hash,
- (GEqualFunc) nmp_object_id_equal,
- (GDestroyNotify) nmp_object_unref,
- nm_g_slice_free_fcn(IP6RoutesTemporaryNotAvailableData));
- }
-
- now_ms = nm_utils_get_monotonic_timestamp_msec();
- oldest_ms = now_ms;
-
- for (i = 0; i < temporary_not_available->len; i++) {
- const NMPObject *o = temporary_not_available->pdata[i];
-
- data = g_hash_table_lookup(priv->rt6_temporary_not_available, o);
- if (data) {
- if (!data->dirty)
- continue;
- data->dirty = FALSE;
- nm_assert(data->timestamp_ms > 0 && data->timestamp_ms <= now_ms);
- if (now_ms > data->timestamp_ms + MAX_AGE_MS) {
- /* timeout. Could not add this address. */
- _LOGW(LOGD_DEVICE,
- "failure to add IPv6 route: %s",
- nmp_object_to_string(o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
- success = FALSE;
- } else
- oldest_ms = MIN(data->timestamp_ms, oldest_ms);
- continue;
- }
-
- data = g_slice_new0(IP6RoutesTemporaryNotAvailableData);
- data->timestamp_ms = now_ms;
- g_hash_table_insert(priv->rt6_temporary_not_available, (gpointer) nmp_object_ref(o), data);
- }
-
- g_hash_table_iter_init(&iter, priv->rt6_temporary_not_available);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &data)) {
- if (data->dirty)
- g_hash_table_iter_remove(&iter);
- }
-
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
- priv->rt6_temporary_not_available_id =
- g_timeout_add(oldest_ms + MAX_AGE_MS - now_ms, _rt6_temporary_not_available_timeout, self);
-
- return success;
-}
-
-/*****************************************************************************/
-
static void
disconnect_cb(NMDevice * self,
GDBusMethodInvocation *context,
@@ -13543,324 +12799,44 @@ nm_device_is_activating(NMDevice *self)
* handler is actually run. If there's an activation handler scheduled
* we're activating anyway.
*/
- return priv->activation_source_id_4 != 0;
-}
-
-NMProxyConfig *
-nm_device_get_proxy_config(NMDevice *self)
-{
- g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
-
- return NM_DEVICE_GET_PRIVATE(self)->proxy_config;
-}
-
-static void
-nm_device_set_proxy_config(NMDevice *self, const char *pac_url)
-{
- NMDevicePrivate *priv;
- NMConnection * connection;
- NMSettingProxy * s_proxy = NULL;
-
- g_return_if_fail(NM_IS_DEVICE(self));
-
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- g_clear_object(&priv->proxy_config);
- priv->proxy_config = nm_proxy_config_new();
-
- if (pac_url) {
- nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO);
- nm_proxy_config_set_pac_url(priv->proxy_config, pac_url);
- _LOGD(LOGD_PROXY, "proxy: PAC url \"%s\"", pac_url);
- } else
- nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE);
-
- connection = nm_device_get_applied_connection(self);
- if (connection)
- s_proxy = nm_connection_get_setting_proxy(connection);
-
- if (s_proxy)
- nm_proxy_config_merge_setting(priv->proxy_config, s_proxy);
+ return !!priv->activation_idle_source;
}
-/* IP Configuration stuff */
NMDhcpConfig *
nm_device_get_dhcp_config(NMDevice *self, int addr_family)
{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
-
g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
- nm_assert_addr_family(addr_family);
-
- return NM_DEVICE_GET_PRIVATE(self)->dhcp_data_x[IS_IPv4].config;
+ return NM_DEVICE_GET_PRIVATE(self)->ipdhcp_data_x[NM_IS_IPv4(addr_family)].config;
}
-NMIP4Config *
-nm_device_get_ip4_config(NMDevice *self)
+NML3Cfg *
+nm_device_get_l3cfg(NMDevice *self)
{
g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
- return NM_DEVICE_GET_PRIVATE(self)->ip_config_4;
-}
-
-static gboolean
-nm_device_set_ip_config(NMDevice * self,
- int addr_family,
- NMIPConfig *new_config,
- gboolean commit,
- GPtrArray * ip4_dev_route_blacklist)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMIPConfig * old_config;
- gboolean has_changes = FALSE;
- gboolean success = TRUE;
- NMSettingsConnection * settings_connection;
- NMIPRouteTableSyncMode route_table_sync_mode;
-
- nm_assert_addr_family(addr_family);
- nm_assert(!new_config || nm_ip_config_get_addr_family(new_config) == addr_family);
- nm_assert(!new_config
- || (new_config && ({
- int ip_ifindex = nm_device_get_ip_ifindex(self);
-
- (ip_ifindex > 0 && ip_ifindex == nm_ip_config_get_ifindex(new_config));
- })));
- nm_assert(IS_IPv4 || !ip4_dev_route_blacklist);
-
- if (commit && new_config)
- route_table_sync_mode = _get_route_table_sync_mode_stateful(self, addr_family);
- else
- route_table_sync_mode = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE;
-
- _LOGD(LOGD_IPX(IS_IPv4),
- "ip%c-config: update (commit=%d, new-config=" NM_HASH_OBFUSCATE_PTR_FMT
- ", route-table-sync-mode=%d)",
- nm_utils_addr_family_to_char(addr_family),
- commit,
- NM_HASH_OBFUSCATE_PTR(new_config),
- (int) route_table_sync_mode);
-
- /* Always commit to nm-platform to update lifetimes */
- if (commit && new_config) {
- _commit_mtu(self, IS_IPv4 ? NM_IP4_CONFIG(new_config) : priv->ip_config_4);
-
- if (IS_IPv4) {
- success = nm_ip4_config_commit(NM_IP4_CONFIG(new_config),
- nm_device_get_platform(self),
- route_table_sync_mode);
- nm_platform_ip4_dev_route_blacklist_set(nm_device_get_platform(self),
- nm_ip_config_get_ifindex(new_config),
- ip4_dev_route_blacklist);
- } else {
- gs_unref_ptrarray GPtrArray *temporary_not_available = NULL;
-
- success = nm_ip6_config_commit(NM_IP6_CONFIG(new_config),
- nm_device_get_platform(self),
- route_table_sync_mode,
- &temporary_not_available);
-
- if (!_rt6_temporary_not_available_set(self, temporary_not_available))
- success = FALSE;
- }
- }
-
- old_config = priv->ip_config_x[IS_IPv4];
-
- if (new_config && old_config) {
- /* has_changes is set only on relevant changes, because when the configuration changes,
- * this causes a re-read and reset. This should only happen for relevant changes */
- nm_ip_config_replace(old_config, new_config, &has_changes);
- if (has_changes) {
- _LOGD(LOGD_IPX(IS_IPv4),
- "ip%c-config: update IP Config instance (%s)",
- nm_utils_addr_family_to_char(addr_family),
- nm_dbus_object_get_path(NM_DBUS_OBJECT(old_config)));
- }
- } else if (new_config /*&& !old_config*/) {
- has_changes = TRUE;
- priv->ip_config_x[IS_IPv4] = g_object_ref(new_config);
- if (!nm_dbus_object_is_exported(NM_DBUS_OBJECT(new_config)))
- nm_dbus_object_export(NM_DBUS_OBJECT(new_config));
-
- _LOGD(LOGD_IPX(IS_IPv4),
- "ip%c-config: set IP Config instance (%s)",
- nm_utils_addr_family_to_char(addr_family),
- nm_dbus_object_get_path(NM_DBUS_OBJECT(new_config)));
- } else if (old_config /*&& !new_config*/) {
- has_changes = TRUE;
- priv->ip_config_x[IS_IPv4] = NULL;
- _LOGD(LOGD_IPX(IS_IPv4),
- "ip%c-config: clear IP Config instance (%s)",
- nm_utils_addr_family_to_char(addr_family),
- nm_dbus_object_get_path(NM_DBUS_OBJECT(old_config)));
- if (IS_IPv4) {
- /* Device config is invalid if combined config is invalid */
- applied_config_clear(&priv->dev_ip_config_4);
- } else
- priv->needs_ip6_subnet = FALSE;
- }
-
- if (has_changes) {
- if (old_config != priv->ip_config_x[IS_IPv4])
- _notify(self, IS_IPv4 ? PROP_IP4_CONFIG : PROP_IP6_CONFIG);
-
- g_signal_emit(self,
- signals[IS_IPv4 ? IP4_CONFIG_CHANGED : IP6_CONFIG_CHANGED],
- 0,
- priv->ip_config_x[IS_IPv4],
- old_config);
-
- if (old_config != priv->ip_config_x[IS_IPv4])
- nm_dbus_object_clear_and_unexport(&old_config);
-
- if (nm_device_sys_iface_state_is_external(self)
- && (settings_connection = nm_device_get_settings_connection(self))
- && NM_FLAGS_HAS(nm_settings_connection_get_flags(settings_connection),
- NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)
- && nm_active_connection_get_activation_type(NM_ACTIVE_CONNECTION(priv->act_request.obj))
- == NM_ACTIVATION_TYPE_EXTERNAL) {
- gs_unref_object NMConnection *new_connection = NULL;
-
- new_connection = nm_simple_connection_new_clone(
- nm_settings_connection_get_connection(settings_connection));
-
- nm_connection_add_setting(
- new_connection,
- IS_IPv4 ? nm_ip4_config_create_setting(priv->ip_config_4)
- : nm_ip6_config_create_setting(priv->ip_config_6,
- _get_maybe_ipv6_disabled(self)));
-
- nm_settings_connection_update(settings_connection,
- new_connection,
- NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY,
- NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
- NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
- NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET,
- "update-external",
- NULL);
- }
-
- nm_device_queue_recheck_assume(self);
-
- if (!IS_IPv4) {
- if (priv->ndisc)
- ndisc_set_router_config(priv->ndisc, self);
- }
- }
-
- nm_assert(!old_config || old_config == priv->ip_config_x[IS_IPv4]);
-
- return success;
+ return NM_DEVICE_GET_PRIVATE(self)->l3cfg;
}
-static gboolean
-_replace_vpn_config_in_list(GSList **plist, GObject *old, GObject *new)
-{
- GSList *old_link;
-
- /* Below, assert that @new is not yet tracked, but still behave
- * correctly in any case. Don't complain for missing @old since
- * it could have been removed when the parent device became
- * unmanaged. */
-
- if (old && (old_link = g_slist_find(*plist, old))) {
- if (old != new) {
- if (new)
- old_link->data = g_object_ref(new);
- else
- *plist = g_slist_delete_link(*plist, old_link);
- g_object_unref(old);
- }
- return TRUE;
- }
-
- if (new) {
- if (!g_slist_find(*plist, new))
- *plist = g_slist_append(*plist, g_object_ref(new));
- else
- g_return_val_if_reached(TRUE);
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-nm_device_replace_vpn4_config(NMDevice *self, NMIP4Config *old, NMIP4Config *config)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- nm_assert(!old || NM_IS_IP4_CONFIG(old));
- nm_assert(!config || NM_IS_IP4_CONFIG(config));
- nm_assert(!old || nm_ip4_config_get_ifindex(old) == nm_device_get_ip_ifindex(self));
- nm_assert(!config || nm_ip4_config_get_ifindex(config) == nm_device_get_ip_ifindex(self));
-
- if (!_replace_vpn_config_in_list(&priv->vpn_configs_4, (GObject *) old, (GObject *) config))
- return;
-
- /* NULL to use existing configs */
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE))
- _LOGW(LOGD_IP4, "failed to set VPN routes for device");
-}
-
-void
-nm_device_set_dev2_ip_config(NMDevice *self, int addr_family, NMIPConfig *config)
+const NML3ConfigData *
+nm_device_get_l3cd(NMDevice *self, gboolean get_commited)
{
NMDevicePrivate *priv;
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- g_return_if_fail(NM_IS_DEVICE(self));
- g_return_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6));
- g_return_if_fail(!config || nm_ip_config_get_addr_family(config) == addr_family);
+ g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
priv = NM_DEVICE_GET_PRIVATE(self);
- applied_config_init(&priv->dev2_ip_config_x[IS_IPv4], config);
- if (!ip_config_merge_and_apply(self, addr_family, TRUE)) {
- _LOGW(LOGD_IP,
- "failed to set extra device IPv%c configuration",
- nm_utils_addr_family_to_char(addr_family));
- }
-}
-
-void
-nm_device_replace_vpn6_config(NMDevice *self, NMIP6Config *old, NMIP6Config *config)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMDeviceState state;
-
- nm_assert(!old || NM_IS_IP6_CONFIG(old));
- nm_assert(!old || nm_ip6_config_get_ifindex(old) > 0);
- nm_assert(!old || nm_device_get_ip_ifindex(self) == 0
- || nm_device_get_ip_ifindex(self) == nm_ip6_config_get_ifindex(old));
- nm_assert(!config || NM_IS_IP6_CONFIG(config));
- nm_assert(!config || nm_ip6_config_get_ifindex(config) > 0);
- nm_assert(!config || nm_device_get_ip_ifindex(self) == nm_ip6_config_get_ifindex(config));
-
- if (!_replace_vpn_config_in_list(&priv->vpn_configs_6, (GObject *) old, (GObject *) config))
- return;
-
- state = nm_device_get_state(self);
- if (state >= NM_DEVICE_STATE_IP_CONFIG && state <= NM_DEVICE_STATE_ACTIVATED) {
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "failed to set VPN routes for device");
- }
-}
-
-NMIP6Config *
-nm_device_get_ip6_config(NMDevice *self)
-{
- g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
+ if (!priv->l3cfg)
+ return NULL;
- return NM_DEVICE_GET_PRIVATE(self)->ip_config_6;
+ return nm_l3cfg_get_combined_l3cd(priv->l3cfg, get_commited);
}
/*****************************************************************************/
static gboolean
-dispatcher_cleanup(NMDevice *self)
+_dispatcher_cleanup(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -13874,7 +12850,7 @@ dispatcher_cleanup(NMDevice *self)
}
static void
-dispatcher_complete_proceed_state(NMDispatcherCallId *call_id, gpointer user_data)
+_dispatcher_complete_proceed_state(NMDispatcherCallId *call_id, gpointer user_data)
{
NMDevice * self = NM_DEVICE(user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -13894,7 +12870,7 @@ ip_check_pre_up(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (dispatcher_cleanup(self))
+ if (_dispatcher_cleanup(self))
nm_assert_not_reached();
priv->dispatcher.post_state = NM_DEVICE_STATE_SECONDARIES;
@@ -13902,11 +12878,11 @@ ip_check_pre_up(NMDevice *self)
if (!nm_dispatcher_call_device(NM_DISPATCHER_ACTION_PRE_UP,
self,
NULL,
- dispatcher_complete_proceed_state,
+ _dispatcher_complete_proceed_state,
self,
&priv->dispatcher.call_id)) {
/* Just proceed on errors */
- dispatcher_complete_proceed_state(0, self);
+ _dispatcher_complete_proceed_state(0, self);
}
}
@@ -14086,8 +13062,8 @@ nm_device_start_ip_check(NMDevice *self)
g_return_if_fail(!priv->gw_ping.watch);
g_return_if_fail(!priv->gw_ping.timeout);
g_return_if_fail(!priv->gw_ping.pid);
- g_return_if_fail(priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE
- || priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE);
+ g_return_if_fail(priv->ip_data_4.state == NM_DEVICE_IP_STATE_READY
+ || priv->ip_data_6.state == NM_DEVICE_IP_STATE_READY);
connection = nm_device_get_applied_connection(self);
g_assert(connection);
@@ -14098,17 +13074,21 @@ nm_device_start_ip_check(NMDevice *self)
buf[0] = '\0';
if (timeout) {
- const NMPObject *gw;
+ const NMPObject * gw;
+ const NML3ConfigData *l3cd;
- if (priv->ip_config_4 && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) {
- gw = nm_ip4_config_best_default_route_get(priv->ip_config_4);
+ l3cd = priv->l3cfg ? nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE) : NULL;
+ if (!l3cd) {
+ /* pass */
+ } else if (priv->ip_data_4.state == NM_DEVICE_IP_STATE_READY) {
+ gw = nm_l3_config_data_get_best_default_route(l3cd, AF_INET);
if (gw) {
_nm_utils_inet4_ntop(NMP_OBJECT_CAST_IP4_ROUTE(gw)->gateway, buf);
ping_binary = nm_utils_find_helper("ping", "/usr/bin/ping", NULL);
log_domain = LOGD_IP4;
}
- } else if (priv->ip_config_6 && priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) {
- gw = nm_ip6_config_best_default_route_get(priv->ip_config_6);
+ } else if (priv->ip_data_6.state == NM_DEVICE_IP_STATE_READY) {
+ gw = nm_l3_config_data_get_best_default_route(l3cd, AF_INET6);
if (gw) {
_nm_utils_inet6_ntop(&NMP_OBJECT_CAST_IP6_ROUTE(gw)->gateway, buf);
ping_binary = nm_utils_find_helper("ping6", "/usr/bin/ping6", NULL);
@@ -14248,15 +13228,7 @@ nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware)
/* Can only get HW address of some devices when they are up */
nm_device_update_hw_address(self);
- /* when the link comes up, we must restore IP configuration if necessary. */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) {
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE))
- _LOGW(LOGD_IP4, "failed applying IP4 config after bringing link up");
- }
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) {
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "failed applying IP6 config after bringing link up");
- }
+ _dev_l3_cfg_commit(self, TRUE);
return TRUE;
}
@@ -14319,381 +13291,6 @@ nm_device_get_firmware_missing(NMDevice *self)
return NM_DEVICE_GET_PRIVATE(self)->firmware_missing;
}
-static void
-intersect_ext_config(NMDevice * self,
- AppliedConfig *config,
- gboolean intersect_addresses,
- gboolean intersect_routes)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMIPConfig * ext;
- guint32 penalty;
- int family;
-
- if (!config->orig)
- return;
-
- family = nm_ip_config_get_addr_family(config->orig);
- penalty = default_route_metric_penalty_get(self, family);
- ext = family == AF_INET ? (NMIPConfig *) priv->ext_ip_config_4
- : (NMIPConfig *) priv->ext_ip_config_6;
-
- if (config->current) {
- nm_ip_config_intersect(config->current,
- ext,
- intersect_addresses,
- intersect_routes,
- penalty);
- } else {
- config->current = nm_ip_config_intersect_alloc(config->orig,
- ext,
- intersect_addresses,
- intersect_routes,
- penalty);
- }
-}
-
-static gboolean
-update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- int ifindex;
- GSList * iter;
- gboolean is_up;
-
- nm_assert_addr_family(addr_family);
-
- ifindex = nm_device_get_ip_ifindex(self);
- if (!ifindex)
- return FALSE;
-
- is_up = nm_platform_link_is_up(nm_device_get_platform(self), ifindex);
-
- if (NM_IS_IPv4(addr_family)) {
- g_clear_object(&priv->ext_ip_config_4);
- priv->ext_ip_config_4 = nm_ip4_config_capture(nm_device_get_multi_index(self),
- nm_device_get_platform(self),
- ifindex);
- if (priv->ext_ip_config_4) {
- if (intersect_configs) {
- /* This function was called upon external changes. Remove the configuration
- * (addresses,routes) that is no longer present externally from the internal
- * config. This way, we don't re-add addresses that were manually removed
- * by the user. */
- if (priv->con_ip_config_4) {
- nm_ip4_config_intersect(priv->con_ip_config_4,
- priv->ext_ip_config_4,
- TRUE,
- is_up,
- default_route_metric_penalty_get(self, AF_INET));
- }
-
- intersect_ext_config(self, &priv->dev_ip_config_4, TRUE, is_up);
- intersect_ext_config(self, &priv->dev2_ip_config_4, TRUE, is_up);
-
- for (iter = priv->vpn_configs_4; iter; iter = iter->next)
- nm_ip4_config_intersect(iter->data, priv->ext_ip_config_4, TRUE, is_up, 0);
- }
-
- /* Remove parts from ext_ip_config_4 to only contain the information that
- * was configured externally -- we already have the same configuration from
- * internal origins. */
- if (priv->con_ip_config_4) {
- nm_ip4_config_subtract(priv->ext_ip_config_4,
- priv->con_ip_config_4,
- default_route_metric_penalty_get(self, AF_INET));
- }
- if (applied_config_get_current(&priv->dev_ip_config_4)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_4,
- applied_config_get_current(&priv->dev_ip_config_4),
- default_route_metric_penalty_get(self, AF_INET));
- }
- if (applied_config_get_current(&priv->dev2_ip_config_4)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_4,
- applied_config_get_current(&priv->dev2_ip_config_4),
- default_route_metric_penalty_get(self, AF_INET));
- }
- for (iter = priv->vpn_configs_4; iter; iter = iter->next)
- nm_ip4_config_subtract(priv->ext_ip_config_4, iter->data, 0);
- }
-
- } else {
- nm_assert(!NM_IS_IPv4(addr_family));
-
- g_clear_object(&priv->ext_ip_config_6);
- g_clear_object(&priv->ext_ip6_config_captured);
- priv->ext_ip6_config_captured =
- nm_ip6_config_capture(nm_device_get_multi_index(self),
- nm_device_get_platform(self),
- ifindex,
- NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
- if (priv->ext_ip6_config_captured) {
- priv->ext_ip_config_6 = nm_ip6_config_new_cloned(priv->ext_ip6_config_captured);
-
- if (intersect_configs) {
- /* This function was called upon external changes. Remove the configuration
- * (addresses,routes) that is no longer present externally from the internal
- * config. This way, we don't re-add addresses that were manually removed
- * by the user. */
- if (priv->con_ip_config_6) {
- nm_ip6_config_intersect(priv->con_ip_config_6,
- priv->ext_ip_config_6,
- is_up,
- is_up,
- default_route_metric_penalty_get(self, AF_INET6));
- }
-
- intersect_ext_config(self, &priv->ac_ip6_config, is_up, is_up);
- intersect_ext_config(self, &priv->dhcp6.ip6_config, is_up, is_up);
- intersect_ext_config(self, &priv->dev2_ip_config_6, is_up, is_up);
-
- for (iter = priv->vpn_configs_6; iter; iter = iter->next)
- nm_ip6_config_intersect(iter->data, priv->ext_ip_config_6, is_up, is_up, 0);
-
- if (is_up && priv->ipv6ll_has
- && !nm_ip6_config_lookup_address(priv->ext_ip_config_6, &priv->ipv6ll_addr))
- priv->ipv6ll_has = FALSE;
- }
-
- /* Remove parts from ext_ip_config_6 to only contain the information that
- * was configured externally -- we already have the same configuration from
- * internal origins. */
- if (priv->con_ip_config_6) {
- nm_ip6_config_subtract(priv->ext_ip_config_6,
- priv->con_ip_config_6,
- default_route_metric_penalty_get(self, AF_INET6));
- }
- if (applied_config_get_current(&priv->ac_ip6_config)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_6,
- applied_config_get_current(&priv->ac_ip6_config),
- default_route_metric_penalty_get(self, AF_INET6));
- }
- if (applied_config_get_current(&priv->dhcp6.ip6_config)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_6,
- applied_config_get_current(&priv->dhcp6.ip6_config),
- default_route_metric_penalty_get(self, AF_INET6));
- }
- if (applied_config_get_current(&priv->dev2_ip_config_6)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_6,
- applied_config_get_current(&priv->dev2_ip_config_6),
- default_route_metric_penalty_get(self, AF_INET6));
- }
- for (iter = priv->vpn_configs_6; iter; iter = iter->next)
- nm_ip6_config_subtract(priv->ext_ip_config_6, iter->data, 0);
- }
- }
-
- return TRUE;
-}
-
-static void
-update_ip_config(NMDevice *self, int addr_family)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- nm_assert_addr_family(addr_family);
-
- if (NM_IS_IPv4(addr_family))
- priv->update_ip_config_completed_v4 = TRUE;
- else
- priv->update_ip_config_completed_v6 = TRUE;
-
- if (update_ext_ip_config(self, addr_family, TRUE)) {
- if (NM_IS_IPv4(addr_family)) {
- if (priv->ext_ip_config_4)
- ip_config_merge_and_apply(self, AF_INET, FALSE);
- } else {
- if (priv->ext_ip6_config_captured)
- ip_config_merge_and_apply(self, AF_INET6, FALSE);
- }
- }
-}
-
-void
-nm_device_capture_initial_config(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- if (!priv->update_ip_config_completed_v4)
- update_ip_config(self, AF_INET);
- if (!priv->update_ip_config_completed_v6)
- update_ip_config(self, AF_INET6);
-}
-
-static gboolean
-queued_ip_config_change(NMDevice *self, int addr_family)
-{
- NMDevicePrivate *priv;
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
-
- g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE);
-
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- /* Wait for any queued state changes */
- if (priv->queued_state.id)
- return G_SOURCE_CONTINUE;
-
- /* If a commit is scheduled, this function would potentially interfere with
- * it changing IP configurations before they are applied. Postpone the
- * update in such case.
- */
- if (priv->activation_source_id_x[IS_IPv4] != 0
- && priv->activation_source_func_x[IS_IPv4]
- == activate_stage5_ip_config_result_x_fcn(addr_family))
- return G_SOURCE_CONTINUE;
-
- priv->queued_ip_config_id_x[IS_IPv4] = 0;
-
- update_ip_config(self, addr_family);
-
- if (!IS_IPv4) {
- /* Check whether we need to complete waiting for link-local.
- * We are also called from an idle handler, so no problem doing state transitions
- * now. */
- linklocal6_check_complete(self);
- }
-
- if (!IS_IPv4) {
- NMPlatform * platform;
- GSList * dad6_failed_addrs, *iter;
- const NMPlatformLink *pllink;
-
- dad6_failed_addrs = g_steal_pointer(&priv->dad6_failed_addrs);
-
- if (priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state < NM_DEVICE_STATE_DEACTIVATING
- && priv->ifindex > 0 && !nm_device_sys_iface_state_is_external(self)
- && (platform = nm_device_get_platform(self))
- && (pllink = nm_platform_link_get(platform, priv->ifindex))
- && (pllink->n_ifi_flags & IFF_UP)) {
- gboolean need_ipv6ll = FALSE;
- NMNDiscConfigMap ndisc_config_changed = NM_NDISC_CONFIG_NONE;
-
- /* Handle DAD failures */
- for (iter = dad6_failed_addrs; iter; iter = iter->next) {
- const NMPObject * obj = iter->data;
- const NMPlatformIP6Address *addr;
-
- if (!nm_ndisc_dad_addr_is_fail_candidate(platform, obj))
- continue;
-
- addr = NMP_OBJECT_CAST_IP6_ADDRESS(obj);
-
- _LOGI(LOGD_IP6,
- "ipv6: duplicate address check failed for the %s address",
- nm_platform_ip6_address_to_string(addr, NULL, 0));
-
- if (IN6_IS_ADDR_LINKLOCAL(&addr->address))
- need_ipv6ll = TRUE;
- else if (priv->ndisc)
- ndisc_config_changed |= nm_ndisc_dad_failed(priv->ndisc, &addr->address, FALSE);
- }
-
- if (ndisc_config_changed != NM_NDISC_CONFIG_NONE)
- nm_ndisc_emit_config_change(priv->ndisc, ndisc_config_changed);
-
- /* If no IPv6 link-local address exists but other addresses do then we
- * must add the LL address to remain conformant with RFC 3513 chapter 2.1
- * ("Addressing Model"): "All interfaces are required to have at least
- * one link-local unicast address".
- */
- if (priv->ip_config_6 && nm_ip6_config_get_num_addresses(priv->ip_config_6))
- need_ipv6ll = TRUE;
- if (need_ipv6ll)
- check_and_add_ipv6ll_addr(self);
- }
-
- g_slist_free_full(dad6_failed_addrs, (GDestroyNotify) nmp_object_unref);
- }
-
- if (!IS_IPv4) {
- /* Check if DAD is still pending */
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF && priv->dad6_ip6_config
- && priv->ext_ip6_config_captured
- && !nm_ip6_config_has_any_dad_pending(priv->ext_ip6_config_captured,
- priv->dad6_ip6_config)) {
- _LOGD(LOGD_DEVICE | LOGD_IP6, "IPv6 DAD terminated");
- g_clear_object(&priv->dad6_ip6_config);
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE);
- check_ip_state(self, FALSE, TRUE);
- if (priv->rt6_temporary_not_available)
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- }
- }
-
- set_unmanaged_external_down(self, TRUE);
-
- return G_SOURCE_REMOVE;
-}
-
-static gboolean
-queued_ip4_config_change(gpointer user_data)
-{
- return queued_ip_config_change(user_data, AF_INET);
-}
-
-static gboolean
-queued_ip6_config_change(gpointer user_data)
-{
- return queued_ip_config_change(user_data, AF_INET6);
-}
-
-static void
-device_ipx_changed(NMPlatform * platform,
- int obj_type_i,
- int ifindex,
- gconstpointer platform_object,
- int change_type_i,
- NMDevice * self)
-{
- const NMPObjectType obj_type = obj_type_i;
- const NMPlatformSignalChangeType change_type = change_type_i;
- NMDevicePrivate * priv;
- const NMPlatformIP6Address * addr;
-
- if (nm_device_get_ip_ifindex(self) != ifindex)
- return;
-
- if (!nm_device_is_real(self))
- return;
-
- if (nm_device_get_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT)) {
- /* ignore all platform signals until the link is initialized in platform. */
- return;
- }
-
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- switch (obj_type) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- if (!priv->queued_ip_config_id_4) {
- priv->queued_ip_config_id_4 = g_idle_add(queued_ip4_config_change, self);
- _LOGD(LOGD_DEVICE, "queued IP4 config change");
- }
- break;
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- addr = platform_object;
-
- if (priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state < NM_DEVICE_STATE_DEACTIVATING
- && nm_ndisc_dad_addr_is_fail_candidate_event(change_type, addr)) {
- priv->dad6_failed_addrs =
- g_slist_prepend(priv->dad6_failed_addrs,
- (gpointer) nmp_object_ref(NMP_OBJECT_UP_CAST(addr)));
- }
-
- /* fall-through */
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- if (!priv->queued_ip_config_id_6) {
- priv->queued_ip_config_id_6 = g_idle_add(queued_ip6_config_change, self);
- _LOGD(LOGD_DEVICE, "queued IP6 config change");
- }
- break;
- default:
- g_return_if_reached();
- }
-}
-
/*****************************************************************************/
NM_UTILS_FLAGS2STR_DEFINE(nm_unmanaged_flags2str,
@@ -14946,12 +13543,6 @@ _set_unmanaged_flags(NMDevice * self,
nm_device_set_unmanaged_flags(self, NM_UNMANAGED_USER_SETTINGS, !!unmanaged);
}
- /* trigger an initial update of IP configuration. */
- nm_assert_se(!nm_clear_g_source(&priv->queued_ip_config_id_4));
- nm_assert_se(!nm_clear_g_source(&priv->queued_ip_config_id_6));
- priv->queued_ip_config_id_4 = g_idle_add(queued_ip4_config_change, self);
- priv->queued_ip_config_id_6 = g_idle_add(queued_ip6_config_change, self);
-
if (priv->pending_actions.len == 0) {
do_notify_has_pending_actions = TRUE;
had_pending_actions = nm_device_has_pending_action(self);
@@ -15303,9 +13894,13 @@ nm_device_update_metered(NMDevice *self)
/* Try to guess a value using the metered flag in IP configuration */
if (value == NM_METERED_INVALID) {
- if (priv->ip_config_4 && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE
- && nm_ip4_config_get_metered(priv->ip_config_4))
- value = NM_METERED_GUESS_YES;
+ if (priv->l3cfg) {
+ const NML3ConfigData *l3cd;
+
+ l3cd = nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE);
+ if (l3cd && nm_l3_config_data_get_metered(l3cd))
+ value = NM_METERED_GUESS_YES;
+ }
}
/* Otherwise, look at connection type. For Bluetooth, we look at the type of
@@ -15876,12 +14471,11 @@ _cancel_activation(NMDevice *self)
priv->fw_state = FIREWALL_STATE_INITIALIZED;
}
- dispatcher_cleanup(self);
+ _dispatcher_cleanup(self);
ip_check_gw_ping_cleanup(self);
/* Break the activation chain */
- activation_source_clear(self, AF_INET);
- activation_source_clear(self, AF_INET6);
+ activation_source_clear(self);
}
static void
@@ -15911,17 +14505,13 @@ _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type)
queued_state_clear(self);
- nm_clear_pointer(&priv->shared_ip_handle, nm_netns_shared_ip_release);
-
for (i = 0; i < 2; i++)
nm_clear_pointer(&priv->hostname_resolver_x[i], _hostname_resolver_free);
_cleanup_ip_pre(self, AF_INET, cleanup_type);
_cleanup_ip_pre(self, AF_INET6, cleanup_type);
- priv->ip_config_started = FALSE;
- nm_clear_g_source_inst(&priv->ip_req_timeout_source_4);
- nm_clear_g_source_inst(&priv->ip_req_timeout_source_6);
+ _dev_ip_state_req_timeout_cancel(self, AF_UNSPEC);
}
static void
@@ -15929,11 +14519,9 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- priv->v4_commit_first_time = TRUE;
- priv->v6_commit_first_time = TRUE;
-
priv->v4_route_table_initialized = FALSE;
priv->v6_route_table_initialized = FALSE;
+ priv->l3config_merge_flags_has = FALSE;
priv->v4_route_table_all_sync_before = FALSE;
priv->v6_route_table_all_sync_before = FALSE;
@@ -15941,42 +14529,9 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type)
priv->default_route_metric_penalty_ip4_has = FALSE;
priv->default_route_metric_penalty_ip6_has = FALSE;
- priv->linklocal6_dad_counter = 0;
-
priv->mtu_force_set_done = FALSE;
- /* Clean up IP configs; this does not actually deconfigure the
- * interface; the caller must flush routes and addresses explicitly.
- */
- nm_device_set_ip_config(self, AF_INET, NULL, TRUE, NULL);
- nm_device_set_ip_config(self, AF_INET6, NULL, TRUE, NULL);
- g_clear_object(&priv->proxy_config);
- g_clear_object(&priv->con_ip_config_4);
- applied_config_clear(&priv->dev_ip_config_4);
- applied_config_clear(&priv->dev2_ip_config_4);
- g_clear_object(&priv->ext_ip_config_4);
- g_clear_object(&priv->ip_config_4);
- g_clear_object(&priv->con_ip_config_6);
- applied_config_clear(&priv->ac_ip6_config);
- g_clear_object(&priv->ext_ip_config_6);
- g_clear_object(&priv->ext_ip6_config_captured);
- applied_config_clear(&priv->dev2_ip_config_6);
- g_clear_object(&priv->ip_config_6);
- g_clear_object(&priv->dad6_ip6_config);
- priv->ipv6ll_has = FALSE;
- memset(&priv->ipv6ll_addr, 0, sizeof(priv->ipv6ll_addr));
-
- nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref);
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
-
- g_slist_free_full(priv->vpn_configs_4, g_object_unref);
- priv->vpn_configs_4 = NULL;
- g_slist_free_full(priv->vpn_configs_6, g_object_unref);
- priv->vpn_configs_6 = NULL;
-
- /* We no longer accept the delegations. nm_device_set_ip_config(NULL)
- * above disables them. */
- nm_assert(priv->needs_ip6_subnet == FALSE);
+ priv->needs_ip6_subnet = FALSE;
if (priv->act_request.obj) {
nm_active_connection_set_default(NM_ACTIVE_CONNECTION(priv->act_request.obj),
@@ -15998,6 +14553,9 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type)
* or ATM device).
*/
_set_ip_ifindex(self, 0, NULL);
+
+ nm_clear_g_source_inst(&priv->ip_data_4.check_async_source);
+ nm_clear_g_source_inst(&priv->ip_data_6.check_async_source);
}
/*
@@ -16029,7 +14587,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
/* Turn off kernel IPv6 */
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
- set_disable_ipv6(self, "1");
+ _dev_sysctl_set_disable_ipv6(self, TRUE);
nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", "0");
}
@@ -16146,18 +14704,19 @@ deactivate_reset_hw_addr(NMDevice *self)
static char *
find_dhcp4_address(NMDevice *self)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- const NMPlatformIP4Address *a;
- NMDedupMultiIter ipconf_iter;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const NMPObject *obj;
- if (!priv->ip_config_4)
+ if (!priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_4].d)
return NULL;
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, priv->ip_config_4, &a) {
- if (a->addr_source == NM_IP_CONFIG_SOURCE_DHCP)
- return nm_utils_inet4_ntop_dup(a->address);
- }
- return NULL;
+ obj = nm_l3_config_data_get_first_obj(priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_4].d,
+ NMP_OBJECT_TYPE_IP4_ADDRESS,
+ NULL);
+ if (!obj)
+ return NULL;
+
+ return nm_utils_inet4_ntop_dup(NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address);
}
void
@@ -16169,7 +14728,6 @@ nm_device_spawn_iface_helper(NMDevice *self)
GError * error = NULL;
const char * method;
GPtrArray * argv;
- gs_free char * dhcp4_address = NULL;
char * logging_backend;
NMUtilsStableType stable_type;
const char * stable_id;
@@ -16214,10 +14772,9 @@ nm_device_spawn_iface_helper(NMDevice *self)
g_ptr_array_add(argv, g_strdup("--log-domains"));
g_ptr_array_add(argv, g_strdup(nm_logging_domains_to_string()));
- dhcp4_address = find_dhcp4_address(self);
-
method = nm_device_get_effective_ip_config_method(self, AF_INET);
if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
+ char * dhcp4_address;
NMSettingIPConfig *s_ip4;
s_ip4 = nm_connection_get_setting_ip4_config(connection);
@@ -16226,34 +14783,36 @@ nm_device_spawn_iface_helper(NMDevice *self)
g_ptr_array_add(argv, g_strdup("--priority4"));
g_ptr_array_add(argv, g_strdup_printf("%u", nm_device_get_route_metric(self, AF_INET)));
- g_ptr_array_add(argv, g_strdup("--dhcp4"));
- g_ptr_array_add(argv, g_strdup(dhcp4_address));
+ dhcp4_address = find_dhcp4_address(self);
+ if (dhcp4_address) {
+ g_ptr_array_add(argv, g_strdup("--dhcp4"));
+ g_ptr_array_add(argv, dhcp4_address);
+ }
+
if (nm_setting_ip_config_get_may_fail(s_ip4) == FALSE)
g_ptr_array_add(argv, g_strdup("--dhcp4-required"));
- if (priv->dhcp_data_4.client) {
- const char *hostname;
- GBytes * client_id;
+ if (priv->ipdhcp_data_4.client) {
+ const NMDhcpClientConfig *config;
+
+ config = nm_dhcp_client_get_config(priv->ipdhcp_data_4.client);
- client_id = nm_dhcp_client_get_client_id(priv->dhcp_data_4.client);
- if (client_id) {
+ if (config->client_id) {
g_ptr_array_add(argv, g_strdup("--dhcp4-clientid"));
g_ptr_array_add(argv,
- nm_utils_bin2hexstr_full(g_bytes_get_data(client_id, NULL),
- g_bytes_get_size(client_id),
+ nm_utils_bin2hexstr_full(g_bytes_get_data(config->client_id, NULL),
+ g_bytes_get_size(config->client_id),
':',
FALSE,
NULL));
}
- hostname = nm_dhcp_client_get_hostname(priv->dhcp_data_4.client);
- if (hostname) {
- if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(priv->dhcp_data_4.client),
- NM_DHCP_CLIENT_FLAGS_USE_FQDN))
+ if (config->hostname) {
+ if (config->use_fqdn)
g_ptr_array_add(argv, g_strdup("--dhcp4-fqdn"));
else
g_ptr_array_add(argv, g_strdup("--dhcp4-hostname"));
- g_ptr_array_add(argv, g_strdup(hostname));
+ g_ptr_array_add(argv, g_strdup(config->hostname));
}
}
@@ -16277,7 +14836,7 @@ nm_device_spawn_iface_helper(NMDevice *self)
g_ptr_array_add(argv, g_strdup("--slaac-required"));
g_ptr_array_add(argv, g_strdup("--slaac-tempaddr"));
- g_ptr_array_add(argv, g_strdup_printf("%d", priv->ndisc_use_tempaddr));
+ g_ptr_array_add(argv, g_strdup_printf("%d", (int) _prop_get_ipv6_ip6_privacy(self)));
if (nm_device_get_ip_iface_identifier(self, &iid, FALSE)) {
g_ptr_array_add(argv, g_strdup("--iid"));
@@ -16328,28 +14887,11 @@ nm_device_spawn_iface_helper(NMDevice *self)
/*****************************************************************************/
-static gboolean
-ip_config_valid(NMDeviceState state)
-{
- return (state == NM_DEVICE_STATE_UNMANAGED)
- || (state >= NM_DEVICE_STATE_IP_CHECK && state <= NM_DEVICE_STATE_DEACTIVATING);
-}
-
-static void
-notify_ip_properties(NMDevice *self)
-{
- _notify(self, PROP_IP_IFACE);
- _notify(self, PROP_IP4_CONFIG);
- _notify(self, PROP_DHCP4_CONFIG);
- _notify(self, PROP_IP6_CONFIG);
- _notify(self, PROP_DHCP6_CONFIG);
-}
-
static void
ip6_managed_setup(NMDevice *self)
{
- set_nm_ipv6ll(self, TRUE);
- set_disable_ipv6(self, "1");
+ _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_NONE);
+ _dev_sysctl_set_disable_ipv6(self, TRUE);
nm_device_sysctl_ip_conf_set(self, AF_INET6, "accept_ra", "0");
nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", "0");
nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "0");
@@ -16483,9 +15025,9 @@ deactivate_dispatcher_complete(NMDispatcherCallId *call_id, gpointer user_data)
static void
_set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, gboolean quitting)
{
- NMDevicePrivate *priv;
- NMDeviceState old_state;
- gs_unref_object NMActRequest *req = NULL;
+ gs_unref_object NMActRequest *req = NULL;
+ NMDevicePrivate * priv;
+ NMDeviceState old_state;
gboolean no_firmware = FALSE;
NMSettingsConnection * sett_conn;
NMSettingSriov * s_sriov;
@@ -16495,8 +15037,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
priv = NM_DEVICE_GET_PRIVATE(self);
- /* Track re-entry */
- g_warn_if_fail(priv->in_state_changed == FALSE);
+ g_return_if_fail(priv->in_state_changed == 0);
old_state = priv->state;
@@ -16533,14 +15074,14 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
* by the device not having any pending action anymore
* we add one here that gets removed at the end of the function */
nm_device_add_pending_action(self, NM_PENDING_ACTION_IN_STATE_CHANGE, TRUE);
- priv->in_state_changed = TRUE;
+ priv->in_state_changed++;
priv->state = state;
priv->state_reason = reason;
queued_state_clear(self);
- dispatcher_cleanup(self);
+ _dispatcher_cleanup(self);
nm_clear_g_cancellable(&priv->deactivating_cancellable);
@@ -16597,15 +15138,15 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
nm_device_cleanup(self, reason, CLEANUP_TYPE_DECONFIGURE);
nm_device_take_down(self, TRUE);
nm_device_hw_addr_reset(self, "unmanage");
- set_nm_ipv6ll(self, FALSE);
- restore_ip6_properties(self);
+ _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_EUI64);
+ _dev_sysctl_restore_ip6_properties(self);
}
}
nm_device_sys_iface_state_set(self, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL);
break;
case NM_DEVICE_STATE_UNAVAILABLE:
if (old_state == NM_DEVICE_STATE_UNMANAGED) {
- save_ip6_properties(self);
+ _dev_sysctl_save_ip6_properties(self);
if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED)
ip6_managed_setup(self);
device_init_static_sriov_num_vfs(self);
@@ -16634,7 +15175,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
/* Ensure devices that previously assumed a connection now have
* userspace IPv6LL enabled.
*/
- set_nm_ipv6ll(self, TRUE);
+ _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_NONE);
nm_device_cleanup(self, reason, CLEANUP_TYPE_DECONFIGURE);
} else if (old_state < NM_DEVICE_STATE_DISCONNECTED) {
@@ -16747,9 +15288,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
_LOGI(LOGD_DEVICE, "Activation: successful, device activated.");
nm_device_update_metered(self);
nm_dispatcher_call_device(NM_DISPATCHER_ACTION_UP, self, req, NULL, NULL, NULL);
-
- if (priv->proxy_config)
- _pacrunner_manager_add(self);
+ _pacrunner_manager_add(self);
break;
case NM_DEVICE_STATE_FAILED:
/* Usually upon failure the activation chain is interrupted in
@@ -16809,11 +15348,6 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
fw_change_zone(self);
} else
nm_device_start_ip_check(self);
-
- /* IP-related properties are only valid when the device has IP configuration;
- * now that it does, ensure their change notifications are emitted.
- */
- notify_ip_properties(self);
break;
}
case NM_DEVICE_STATE_SECONDARIES:
@@ -16836,18 +15370,13 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
}
}
- /* IP-related properties are only valid when the device has IP configuration.
- * If it no longer does, ensure their change notifications are emitted.
- */
- if (ip_config_valid(old_state) && !ip_config_valid(state))
- notify_ip_properties(self);
-
concheck_now = NM_IN_SET(state, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_DISCONNECTED)
|| old_state >= NM_DEVICE_STATE_ACTIVATED;
concheck_update_interval(self, AF_INET, concheck_now);
concheck_update_interval(self, AF_INET6, concheck_now);
- priv->in_state_changed = FALSE;
+ priv->in_state_changed--;
+
nm_device_remove_pending_action(self, NM_PENDING_ACTION_IN_STATE_CHANGE, TRUE);
if ((old_state > NM_DEVICE_STATE_UNMANAGED) != (state > NM_DEVICE_STATE_UNMANAGED))
@@ -17869,15 +16398,16 @@ nm_device_clear_dns_lookup_data(NMDevice *self)
const char *
nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_wait)
{
- NMDevicePrivate * priv;
const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMDevicePrivate * priv;
HostnameResolver *resolver;
- NMIPConfig * ip_config;
const char * method;
+ int ifindex;
gboolean address_changed = FALSE;
gs_unref_object GInetAddress *new_address = NULL;
g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
+
priv = NM_DEVICE_GET_PRIVATE(self);
/* If the device is not supposed to have addresses,
@@ -17917,39 +16447,29 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean
/* Determine the most suitable address of the interface
* and whether it changed from the previous lookup */
- ip_config = priv->ip_config_x[IS_IPv4];
- if (ip_config) {
- const NMPlatformIPAddress *addr = NULL;
-
- if (IS_IPv4) {
- addr = nm_ip_config_get_first_address(ip_config);
- } else {
- /* For IPv6 prefer, in order:
- * - !link-local, !deprecated
- * - !link-local, deprecated
- * - link-local
- */
- addr = nm_ip_config_find_first_address(ip_config,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL);
- if (!addr) {
- addr = nm_ip_config_find_first_address(
- ip_config,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED);
- }
- if (!addr) {
- addr = nm_ip_config_find_first_address(ip_config,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY);
+ ifindex = nm_device_get_ip_ifindex(self);
+ if (ifindex > 0) {
+ NMPLookup lookup;
+ const NMDedupMultiHeadEntry *head_entry;
+ const NMDedupMultiEntry * iter;
+
+ /* FIXME(l3cfg): now we lookup the address from platform. Should we instead look
+ * it up from NML3Cfg? That is, take an address that we want to configure as
+ * opposed to an address that is configured? */
+ head_entry = nm_platform_lookup(
+ nm_device_get_platform(self),
+ nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex));
+
+ if (head_entry) {
+ c_list_for_each_entry (iter, &head_entry->lst_entries_head, lst_entries) {
+ const NMPlatformIPAddress *addr = NMP_OBJECT_CAST_IP_ADDRESS(iter->obj);
+
+ new_address = g_inet_address_new_from_bytes(addr->address_ptr,
+ IS_IPv4 ? G_SOCKET_FAMILY_IPV4
+ : G_SOCKET_FAMILY_IPV6);
+ break;
}
}
-
- if (addr) {
- new_address = g_inet_address_new_from_bytes(addr->address_ptr,
- IS_IPv4 ? G_SOCKET_FAMILY_IPV4
- : G_SOCKET_FAMILY_IPV6);
- }
}
if (new_address && resolver->address) {
@@ -18023,11 +16543,7 @@ _activation_func_to_string(ActivationHandleFunc func)
G_STMT_END
FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage1_device_prepare);
FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage2_device_config);
- FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage3_ip_config_start);
- FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage4_ip_config_timeout_4);
- FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage4_ip_config_timeout_6);
- FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage5_ip_config_result_4);
- FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage5_ip_config_result_6);
+ FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage3_ip_config);
g_return_val_if_reached("unknown");
}
@@ -18059,13 +16575,10 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
nm_utils_str_utf8safe_escape_cp(priv->iface, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
break;
case PROP_IP_IFACE:
- if (ip_config_valid(priv->state)) {
- g_value_take_string(
- value,
- nm_utils_str_utf8safe_escape_cp(nm_device_get_ip_iface(self),
- NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
- } else
- g_value_set_string(value, NULL);
+ g_value_take_string(
+ value,
+ nm_utils_str_utf8safe_escape_cp(nm_device_get_ip_iface(self),
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
break;
case PROP_IFINDEX:
g_value_set_int(value, priv->ifindex);
@@ -18100,24 +16613,16 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
g_value_set_uint(value, priv->mtu);
break;
case PROP_IP4_CONFIG:
- nm_dbus_utils_g_value_set_object_path(value,
- ip_config_valid(priv->state) ? priv->ip_config_4
- : NULL);
+ nm_dbus_utils_g_value_set_object_path(value, priv->l3ipdata_4.ip_config);
break;
case PROP_DHCP4_CONFIG:
- nm_dbus_utils_g_value_set_object_path(
- value,
- ip_config_valid(priv->state) ? priv->dhcp_data_4.config : NULL);
+ nm_dbus_utils_g_value_set_object_path(value, priv->ipdhcp_data_4.config);
break;
case PROP_IP6_CONFIG:
- nm_dbus_utils_g_value_set_object_path(value,
- ip_config_valid(priv->state) ? priv->ip_config_6
- : NULL);
+ nm_dbus_utils_g_value_set_object_path(value, priv->l3ipdata_6.ip_config);
break;
case PROP_DHCP6_CONFIG:
- nm_dbus_utils_g_value_set_object_path(
- value,
- ip_config_valid(priv->state) ? priv->dhcp_data_6.config : NULL);
+ nm_dbus_utils_g_value_set_object_path(value, priv->ipdhcp_data_6.config);
break;
case PROP_STATE:
g_value_set_uint(value, priv->state);
@@ -18344,6 +16849,8 @@ nm_device_init(NMDevice *self)
c_list_init(&self->devices_lst);
c_list_init(&priv->slaves);
+ priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_NONE;
+
priv->concheck_x[0].state = NM_CONNECTIVITY_UNKNOWN;
priv->concheck_x[1].state = NM_CONNECTIVITY_UNKNOWN;
@@ -18369,9 +16876,6 @@ nm_device_init(NMDevice *self)
priv->ip6_saved_properties = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, g_free);
priv->sys_iface_state_ = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL;
- priv->v4_commit_first_time = TRUE;
- priv->v6_commit_first_time = TRUE;
-
priv->promisc_reset = NM_OPTION_BOOL_DEFAULT;
}
@@ -18428,24 +16932,7 @@ constructed(GObject *object)
if (NM_DEVICE_GET_CLASS(self)->get_generic_capabilities)
priv->capabilities |= NM_DEVICE_GET_CLASS(self)->get_generic_capabilities(self);
- /* Watch for external IP config changes */
platform = nm_device_get_platform(self);
- g_signal_connect(platform,
- NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
- G_CALLBACK(device_ipx_changed),
- self);
- g_signal_connect(platform,
- NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
- G_CALLBACK(device_ipx_changed),
- self);
- g_signal_connect(platform,
- NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
- G_CALLBACK(device_ipx_changed),
- self);
- g_signal_connect(platform,
- NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
- G_CALLBACK(device_ipx_changed),
- self);
g_signal_connect(platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK(link_changed_cb), self);
priv->manager = g_object_ref(NM_MANAGER_GET);
@@ -18497,15 +16984,12 @@ dispose(GObject *object)
_parent_set_ifindex(self, 0, FALSE);
platform = nm_device_get_platform(self);
- g_signal_handlers_disconnect_by_func(platform, G_CALLBACK(device_ipx_changed), self);
g_signal_handlers_disconnect_by_func(platform, G_CALLBACK(link_changed_cb), self);
- arp_cleanup(self);
-
nm_clear_g_signal_handler(nm_config_get(), &priv->config_changed_id);
nm_clear_g_signal_handler(priv->manager, &priv->ifindex_changed_id);
- dispatcher_cleanup(self);
+ _dispatcher_cleanup(self);
nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id);
@@ -18514,7 +16998,7 @@ dispose(GObject *object)
nm_assert(c_list_is_empty(&priv->slaves));
/* Let the kernel manage IPv6LL again */
- set_nm_ipv6ll(self, FALSE);
+ _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_EUI64);
_cleanup_generic_post(self, CLEANUP_TYPE_KEEP);
@@ -18583,7 +17067,6 @@ finalize(GObject *object)
g_free(priv->hw_addr_perm);
g_free(priv->hw_addr_initial);
g_free(priv->pending_actions.arr);
- g_slist_free_full(priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref);
nm_clear_g_free(&priv->physical_port_id);
g_free(priv->udi);
g_free(priv->path);
@@ -18763,10 +17246,8 @@ nm_device_class_init(NMDeviceClass *klass)
klass->link_changed = link_changed;
- klass->is_available = is_available;
- klass->act_stage2_config = act_stage2_config;
- klass->act_stage3_ip_config_start = act_stage3_ip_config_start;
- klass->act_stage4_ip_config_timeout = act_stage4_ip_config_timeout;
+ klass->is_available = is_available;
+ klass->act_stage2_config = act_stage2_config;
klass->get_type_description = get_type_description;
klass->can_auto_connect = can_auto_connect;
@@ -19098,29 +17579,17 @@ nm_device_class_init(NMDeviceClass *klass)
G_TYPE_BOOLEAN,
0);
- signals[IP4_CONFIG_CHANGED] = g_signal_new(NM_DEVICE_IP4_CONFIG_CHANGED,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 2,
- G_TYPE_OBJECT,
- G_TYPE_OBJECT);
-
- signals[IP6_CONFIG_CHANGED] = g_signal_new(NM_DEVICE_IP6_CONFIG_CHANGED,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 2,
- G_TYPE_OBJECT,
- G_TYPE_OBJECT);
+ signals[L3CD_CHANGED] = g_signal_new(NM_DEVICE_L3CD_CHANGED,
+ G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_POINTER, /* (const NML3ConfigData *l3cd_old) */
+ G_TYPE_POINTER /* (const NML3ConfigData *l3cd_new) */);
signals[IP6_PREFIX_DELEGATED] =
g_signal_new(NM_DEVICE_IP6_PREFIX_DELEGATED,
diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h
index f59b6fa845..54f5b5f929 100644
--- a/src/core/devices/nm-device.h
+++ b/src/core/devices/nm-device.h
@@ -9,13 +9,14 @@
#include <netinet/in.h>
-#include "nm-setting-connection.h"
-#include "nm-dbus-object.h"
-#include "nm-dbus-interface.h"
-#include "nm-connection.h"
-#include "nm-rfkill-manager.h"
#include "NetworkManagerUtils.h"
+#include "nm-connection.h"
+#include "nm-dbus-interface.h"
+#include "nm-dbus-object.h"
#include "nm-device-utils.h"
+#include "nm-l3cfg.h"
+#include "nm-rfkill-manager.h"
+#include "nm-setting-connection.h"
/* Properties */
#define NM_DEVICE_UDI "udi"
@@ -70,8 +71,7 @@
/* Internal signals */
#define NM_DEVICE_DNS_LOOKUP_DONE "dns-lookup-done"
-#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed"
-#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
+#define NM_DEVICE_L3CD_CHANGED "l3cd-changed"
#define NM_DEVICE_IP6_PREFIX_DELEGATED "ip6-prefix-delegated"
#define NM_DEVICE_IP6_SUBNET_NEEDED "ip6-subnet-needed"
#define NM_DEVICE_REMOVED "removed"
@@ -343,15 +343,7 @@ typedef struct _NMDeviceClass {
NMActStageReturn (*act_stage1_prepare)(NMDevice *self, NMDeviceStateReason *out_failure_reason);
NMActStageReturn (*act_stage2_config)(NMDevice *self, NMDeviceStateReason *out_failure_reason);
- NMActStageReturn (*act_stage3_ip_config_start)(NMDevice * self,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason);
- NMActStageReturn (*act_stage4_ip_config_timeout)(NMDevice * self,
- int addr_family,
- NMDeviceStateReason *out_failure_reason);
-
- void (*ip4_config_pre_commit)(NMDevice *self, NMIP4Config *config);
+ void (*act_stage3_ip_config)(NMDevice *self, int addr_family);
/* Async deactivating (in the DEACTIVATING phase) */
void (*deactivate_async)(NMDevice * self,
@@ -459,16 +451,13 @@ const char *nm_device_get_permanent_hw_address_full(NMDevice *self,
gboolean *out_is_fake);
const char *nm_device_get_initial_hw_address(NMDevice *dev);
-NMProxyConfig *nm_device_get_proxy_config(NMDevice *dev);
-
NMDhcpConfig *nm_device_get_dhcp_config(NMDevice *dev, int addr_family);
-NMIP4Config * nm_device_get_ip4_config(NMDevice *dev);
-void nm_device_replace_vpn4_config(NMDevice *dev, NMIP4Config *old, NMIP4Config *config);
-NMIP6Config *nm_device_get_ip6_config(NMDevice *dev);
-void nm_device_replace_vpn6_config(NMDevice *dev, NMIP6Config *old, NMIP6Config *config);
+NML3Cfg *nm_device_get_l3cfg(NMDevice *self);
+
+const NML3ConfigData *nm_device_get_l3cd(NMDevice *self, gboolean get_commited);
-void nm_device_capture_initial_config(NMDevice *dev);
+void nm_device_l3cfg_commit(NMDevice *self, NML3CfgCommitType commit_type, gboolean do_sync);
int nm_device_parent_get_ifindex(NMDevice *dev);
NMDevice *nm_device_parent_get_device(NMDevice *dev);
@@ -546,7 +535,7 @@ RfKillType nm_device_get_rfkill_type(NMDevice *device);
/* IPv6 prefix delegation */
-void nm_device_request_ip6_prefixes(NMDevice *self, int needed_prefixes);
+void nm_device_request_ip6_prefixes(NMDevice *self, guint needed_prefixes);
gboolean nm_device_needs_ip6_subnet(NMDevice *self);
@@ -760,10 +749,6 @@ void nm_device_reapply_settings_immediately(NMDevice *self);
void nm_device_update_firewall_zone(NMDevice *self);
void nm_device_update_metered(NMDevice *self);
-void nm_device_reactivate_ip_config(NMDevice * device,
- int addr_family,
- NMSettingIPConfig *s_ip_old,
- NMSettingIPConfig *s_ip_new);
gboolean nm_device_update_hw_address(NMDevice *self);
void nm_device_update_initial_hw_address(NMDevice *self);
diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c
index 26a5ba002c..9c477a060a 100644
--- a/src/core/devices/ovs/nm-device-ovs-bridge.c
+++ b/src/core/devices/ovs/nm-device-ovs-bridge.c
@@ -66,13 +66,10 @@ get_generic_capabilities(NMDevice *device)
return NM_DEVICE_CAP_IS_SOFTWARE;
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
{
- return NM_ACT_STAGE_RETURN_IP_FAIL;
+ nm_device_devip_set_failed(device, addr_family, NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED);
}
static gboolean
@@ -154,7 +151,7 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass)
device_class->create_and_realize = create_and_realize;
device_class->unrealize = unrealize;
device_class->get_generic_capabilities = get_generic_capabilities;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
device_class->enslave_slave = enslave_slave;
device_class->release_slave = release_slave;
device_class->can_reapply_change_ovs_external_ids = TRUE;
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c
index 46a612aca7..497be1ef1d 100644
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
@@ -119,19 +119,7 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink)
return;
priv->waiting_for_interface = FALSE;
-
- if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG) {
- if (!nm_device_hw_addr_set_cloned(device,
- nm_device_get_applied_connection(device),
- FALSE)) {
- nm_device_state_changed(device,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_CONFIG_FAILED);
- return;
- }
- nm_device_bring_up(device, TRUE, NULL);
- nm_device_activate_schedule_stage3_ip_config_start(device);
- }
+ nm_device_activate_schedule_stage2_device_config(device, FALSE);
}
static gboolean
@@ -189,16 +177,13 @@ set_platform_mtu(NMDevice *device, guint32 mtu)
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
{
NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device);
- NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(device);
+ NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
if (!_is_internal_interface(device))
- return NM_ACT_STAGE_RETURN_IP_FAIL;
+ return NM_ACT_STAGE_RETURN_SUCCESS;
if (nm_device_get_ip_ifindex(device) <= 0) {
_LOGT(LOGD_DEVICE, "waiting for link to appear");
@@ -211,8 +196,7 @@ act_stage3_ip_config_start(NMDevice * device,
return NM_ACT_STAGE_RETURN_FAILURE;
}
- return NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ return NM_ACT_STAGE_RETURN_SUCCESS;
}
static gboolean
@@ -443,7 +427,7 @@ nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass)
device_class->is_available = is_available;
device_class->check_connection_compatible = check_connection_compatible;
device_class->link_changed = link_changed;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
+ device_class->act_stage2_config = act_stage2_config;
device_class->can_unmanaged_external_down = can_unmanaged_external_down;
device_class->set_platform_mtu = set_platform_mtu;
device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired;
diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c
index f11c585235..9a9c260d22 100644
--- a/src/core/devices/ovs/nm-device-ovs-port.c
+++ b/src/core/devices/ovs/nm-device-ovs-port.c
@@ -59,13 +59,10 @@ get_generic_capabilities(NMDevice *device)
return NM_DEVICE_CAP_IS_SOFTWARE;
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
{
- return NM_ACT_STAGE_RETURN_IP_FAIL;
+ nm_device_devip_set_failed(device, addr_family, NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED);
}
static void
@@ -186,7 +183,7 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass)
device_class->get_type_description = get_type_description;
device_class->create_and_realize = create_and_realize;
device_class->get_generic_capabilities = get_generic_capabilities;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
device_class->enslave_slave = enslave_slave;
device_class->release_slave = release_slave;
device_class->can_reapply_change_ovs_external_ids = TRUE;
diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c
index 3398e467e5..7ec7305118 100644
--- a/src/core/devices/team/nm-device-team.c
+++ b/src/core/devices/team/nm-device-team.c
@@ -23,7 +23,6 @@
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-dbus-manager.h"
-#include "nm-ip4-config.h"
#include "libnm-std-aux/nm-dbus-compat.h"
#define _NMLOG_DEVICE_TYPE NMDeviceTeam
diff --git a/src/core/devices/tests/meson.build b/src/core/devices/tests/meson.build
index 1bc883706e..871c320629 100644
--- a/src/core/devices/tests/meson.build
+++ b/src/core/devices/tests/meson.build
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
test_units = [
- 'test-acd',
'test-lldp',
]
diff --git a/src/core/devices/tests/test-acd.c b/src/core/devices/tests/test-acd.c
deleted file mode 100644
index b4b6516549..0000000000
--- a/src/core/devices/tests/test-acd.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "n-acd/src/n-acd.h"
-
-#include <linux/if_ether.h>
-
-#include "devices/nm-acd-manager.h"
-#include "platform/tests/test-common.h"
-
-#define IFACE_VETH0 "nm-test-veth0"
-#define IFACE_VETH1 "nm-test-veth1"
-
-#define ADDR1 0x01010101
-#define ADDR2 0x02020202
-#define ADDR3 0x03030303
-#define ADDR4 0x04040404
-
-/*****************************************************************************/
-
-static gboolean
-_skip_acd_test_check(void)
-{
- NAcd * acd;
- NAcdConfig * config;
- const guint8 hwaddr[ETH_ALEN] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
- int r;
- static int skip = -1;
-
- if (skip == -1) {
- r = n_acd_config_new(&config);
- g_assert(r == 0);
-
- n_acd_config_set_ifindex(config, 1);
- n_acd_config_set_transport(config, N_ACD_TRANSPORT_ETHERNET);
- n_acd_config_set_mac(config, hwaddr, sizeof(hwaddr));
-
- r = n_acd_new(&acd, config);
- n_acd_config_free(config);
- if (r == 0)
- n_acd_unref(acd);
-
- skip = (r != 0);
- }
- return skip;
-}
-
-#define _skip_acd_test() \
- ({ \
- gboolean _skip = _skip_acd_test_check(); \
- \
- if (_skip) \
- g_test_skip("Cannot create NAcd. Running under valgind?"); \
- _skip; \
- })
-
-/*****************************************************************************/
-
-typedef struct {
- int ifindex0;
- int ifindex1;
- const guint8 *hwaddr0;
- const guint8 *hwaddr1;
- size_t hwaddr0_len;
- size_t hwaddr1_len;
-} test_fixture;
-
-static void
-fixture_setup(test_fixture *fixture, gconstpointer user_data)
-{
- /* create veth pair. */
- fixture->ifindex0 =
- nmtstp_link_veth_add(NM_PLATFORM_GET, -1, IFACE_VETH0, IFACE_VETH1)->ifindex;
- fixture->ifindex1 =
- nmtstp_link_get_typed(NM_PLATFORM_GET, -1, IFACE_VETH1, NM_LINK_TYPE_VETH)->ifindex;
-
- g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, fixture->ifindex0, IFF_UP, TRUE) >= 0);
- g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, fixture->ifindex1, IFF_UP, TRUE) >= 0);
-
- fixture->hwaddr0 =
- nm_platform_link_get_address(NM_PLATFORM_GET, fixture->ifindex0, &fixture->hwaddr0_len);
- fixture->hwaddr1 =
- nm_platform_link_get_address(NM_PLATFORM_GET, fixture->ifindex1, &fixture->hwaddr1_len);
-}
-
-typedef struct {
- in_addr_t addresses[8];
- in_addr_t peer_addresses[8];
- gboolean expected_result[8];
-} TestInfo;
-
-static void
-acd_manager_probe_terminated(NMAcdManager *acd_manager, gpointer user_data)
-{
- g_main_loop_quit(user_data);
-}
-
-static void
-test_acd_common(test_fixture *fixture, TestInfo *info)
-{
- nm_auto_free_acdmgr NMAcdManager *manager = NULL;
- nm_auto_unref_gmainloop GMainLoop *loop = NULL;
- int i;
- const guint WAIT_TIME_OPTIMISTIC = 50;
- guint wait_time;
- static const NMAcdCallbacks callbacks = {
- .probe_terminated_callback = acd_manager_probe_terminated,
- .user_data_destroy = (GDestroyNotify) g_main_loop_unref,
- };
- int r;
-
- if (_skip_acd_test())
- return;
-
- /* first, try with a short waittime. We hope that this is long enough
- * to successfully complete the test. Only if that's not the case, we
- * assume the computer is currently busy (high load) and we retry with
- * a longer timeout. */
- wait_time = WAIT_TIME_OPTIMISTIC;
-again:
-
- nm_clear_pointer(&loop, g_main_loop_unref);
- loop = g_main_loop_new(NULL, FALSE);
-
- nm_clear_pointer(&manager, nm_acd_manager_free);
- manager = nm_acd_manager_new(fixture->ifindex0,
- fixture->hwaddr0,
- fixture->hwaddr0_len,
- &callbacks,
- g_main_loop_ref(loop));
- g_assert(manager != NULL);
-
- for (i = 0; info->addresses[i]; i++)
- g_assert(nm_acd_manager_add_address(manager, info->addresses[i]));
-
- for (i = 0; info->peer_addresses[i]; i++) {
- nmtstp_ip4_address_add(NULL,
- FALSE,
- fixture->ifindex1,
- info->peer_addresses[i],
- 24,
- 0,
- 3600,
- 1800,
- 0,
- NULL);
- }
-
- r = nm_acd_manager_start_probe(manager, wait_time);
- g_assert_cmpint(r, ==, 0);
-
- g_assert(nmtst_main_loop_run(loop, 2000));
-
- for (i = 0; info->addresses[i]; i++) {
- gboolean val;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- val = nm_acd_manager_check_address(manager, info->addresses[i]);
- if (val == info->expected_result[i])
- continue;
-
- if (wait_time == WAIT_TIME_OPTIMISTIC) {
- /* probably we just had a glitch and the system took longer than
- * expected. Re-verify with a large timeout this time. */
- wait_time = 1000;
- goto again;
- }
-
- g_error("expected check for address #%d (%s) to %s, but it didn't",
- i,
- _nm_utils_inet4_ntop(info->addresses[i], sbuf),
- info->expected_result[i] ? "detect no duplicated" : "detect a duplicate");
- }
-}
-
-static void
-test_acd_probe_1(test_fixture *fixture, gconstpointer user_data)
-{
- TestInfo info = {.addresses = {ADDR1, ADDR2, ADDR3},
- .peer_addresses = {ADDR4},
- .expected_result = {TRUE, TRUE, TRUE}};
-
- test_acd_common(fixture, &info);
-}
-
-static void
-test_acd_probe_2(test_fixture *fixture, gconstpointer user_data)
-{
- TestInfo info = {.addresses = {ADDR1, ADDR2, ADDR3, ADDR4},
- .peer_addresses = {ADDR3, ADDR2},
- .expected_result = {TRUE, FALSE, FALSE, TRUE}};
-
- test_acd_common(fixture, &info);
-}
-
-static void
-test_acd_announce(test_fixture *fixture, gconstpointer user_data)
-{
- nm_auto_free_acdmgr NMAcdManager *manager = NULL;
- nm_auto_unref_gmainloop GMainLoop *loop = NULL;
- int r;
-
- if (_skip_acd_test())
- return;
-
- manager =
- nm_acd_manager_new(fixture->ifindex0, fixture->hwaddr0, fixture->hwaddr0_len, NULL, NULL);
- g_assert(manager != NULL);
-
- g_assert(nm_acd_manager_add_address(manager, ADDR1));
- g_assert(nm_acd_manager_add_address(manager, ADDR2));
-
- loop = g_main_loop_new(NULL, FALSE);
- r = nm_acd_manager_announce_addresses(manager);
- g_assert_cmpint(r, ==, 0);
- g_assert(!nmtst_main_loop_run(loop, 200));
-}
-
-static void
-fixture_teardown(test_fixture *fixture, gconstpointer user_data)
-{
- nm_platform_link_delete(NM_PLATFORM_GET, fixture->ifindex0);
- nm_platform_link_delete(NM_PLATFORM_GET, fixture->ifindex1);
-}
-
-NMTstpSetupFunc const _nmtstp_setup_platform_func = nm_linux_platform_setup;
-
-void
-_nmtstp_init_tests(int *argc, char ***argv)
-{
- nmtst_init_with_logging(argc, argv, NULL, "ALL");
-}
-
-void
-_nmtstp_setup_tests(void)
-{
- g_test_add("/acd/probe/1",
- test_fixture,
- NULL,
- fixture_setup,
- test_acd_probe_1,
- fixture_teardown);
- g_test_add("/acd/probe/2",
- test_fixture,
- NULL,
- fixture_setup,
- test_acd_probe_2,
- fixture_teardown);
- g_test_add("/acd/announce",
- test_fixture,
- NULL,
- fixture_setup,
- test_acd_announce,
- fixture_teardown);
-}
diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c
index 27a3188b0d..9a1ac8a162 100644
--- a/src/core/devices/wifi/nm-device-iwd.c
+++ b/src/core/devices/wifi/nm-device-iwd.c
@@ -1642,7 +1642,7 @@ network_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data)
_LOGI(LOGD_DEVICE | LOGD_WIFI,
"Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Connected to '%s'.",
ssid);
- nm_device_activate_schedule_stage3_ip_config_start(device);
+ nm_device_activate_schedule_stage3_ip_config(device, FALSE);
return;
@@ -1721,7 +1721,7 @@ act_start_cb(GObject *source, GAsyncResult *res, gpointer user_data)
_LOGI(LOGD_DEVICE | LOGD_WIFI,
"Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Started '%s'.",
ssid);
- nm_device_activate_schedule_stage3_ip_config_start(device);
+ nm_device_activate_schedule_stage3_ip_config(device, FALSE);
return;
@@ -2127,7 +2127,7 @@ assumed_connection_progress_to_ip_config(NMDeviceIwd *self, gboolean was_postpon
* that stage2 is done.
*/
if (was_postponed)
- nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self));
+ nm_device_activate_schedule_stage3_ip_config(NM_DEVICE(self), FALSE);
}
static void
diff --git a/src/core/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c
index 67202a6778..ed74d30ec5 100644
--- a/src/core/devices/wifi/nm-device-wifi-p2p.c
+++ b/src/core/devices/wifi/nm-device-wifi-p2p.c
@@ -14,18 +14,18 @@
#include "NetworkManagerUtils.h"
#include "devices/nm-device-private.h"
-#include "nm-act-request.h"
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-glib-aux/nm-ref-string.h"
-#include "nm-ip4-config.h"
+#include "libnm-platform/nm-platform.h"
+#include "libnm-platform/nmp-object.h"
+#include "nm-act-request.h"
+#include "nm-l3-config-data.h"
#include "nm-manager.h"
#include "nm-manager.h"
#include "nm-setting-wifi-p2p.h"
#include "nm-utils.h"
#include "nm-wifi-p2p-peer.h"
-#include "libnm-platform/nm-platform.h"
-#include "libnm-platform/nmp-object.h"
#include "settings/nm-settings.h"
#define _NMLOG_DEVICE_TYPE NMDeviceWifiP2P
@@ -552,13 +552,11 @@ remove_all_peers(NMDeviceWifiP2P *self)
/*****************************************************************************/
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
{
- NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(device);
+ NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(device);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
gboolean indicate_addressing_running;
NMConnection * connection;
const char * method;
@@ -568,30 +566,30 @@ act_stage3_ip_config_start(NMDevice * device,
method = nm_utils_get_ip_config_method(connection, addr_family);
/* We may have an address assigned by the group owner */
- if (NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) && priv->group_iface
+ if (IS_IPv4 && NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) && priv->group_iface
&& !nm_supplicant_interface_get_p2p_group_owner(priv->group_iface)) {
in_addr_t addr;
guint8 plen;
if (nm_supplicant_interface_get_p2p_assigned_addr(priv->group_iface, &addr, &plen)) {
- NMPlatformIP4Address address = {
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP4Address address = {
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
};
- gs_unref_object NMIP4Config *ip4_config = NULL;
nm_platform_ip4_address_set_addr(&address, addr, plen);
- ip4_config = nm_device_ip4_config_new(device);
- nm_ip4_config_add_address(ip4_config, &address);
+ l3cd = nm_device_create_l3_config_data(device, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_add_address_4(l3cd, &address);
- nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG(ip4_config));
+ nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_READY, l3cd);
/* This just disables the addressing indicator. */
method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
}
}
- if (addr_family == AF_INET)
+ if (IS_IPv4)
indicate_addressing_running = NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
else {
indicate_addressing_running = NM_IN_STRSET(method,
@@ -603,9 +601,6 @@ act_stage3_ip_config_start(NMDevice * device,
nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device),
nm_device_get_ip_ifindex(device),
TRUE);
-
- return NM_DEVICE_CLASS(nm_device_wifi_p2p_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
}
static void
@@ -757,7 +752,7 @@ check_group_iface_ready(NMDeviceWifiP2P *self)
nm_clear_g_source(&priv->sup_timeout_id);
update_disconnect_on_connection_peer_missing(self);
- nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self));
+ nm_device_activate_schedule_stage3_ip_config(NM_DEVICE(self), FALSE);
}
static void
@@ -1286,11 +1281,11 @@ nm_device_wifi_p2p_class_init(NMDeviceWifiP2PClass *klass)
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
- device_class->act_stage1_prepare = act_stage1_prepare;
- device_class->act_stage2_config = act_stage2_config;
- device_class->get_configured_mtu = get_configured_mtu;
- device_class->get_auto_ip_config_method = get_auto_ip_config_method;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->act_stage2_config = act_stage2_config;
+ device_class->get_configured_mtu = get_configured_mtu;
+ device_class->get_auto_ip_config_method = get_auto_ip_config_method;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
device_class->deactivate = deactivate;
device_class->unmanaged_on_quit = unmanaged_on_quit;
diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c
index 6052187488..d654086ba2 100644
--- a/src/core/devices/wifi/nm-device-wifi.c
+++ b/src/core/devices/wifi/nm-device-wifi.c
@@ -32,7 +32,6 @@
#include "nm-setting-wireless-security.h"
#include "nm-setting-8021x.h"
#include "nm-setting-ip4-config.h"
-#include "nm-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-auth-utils.h"
@@ -136,6 +135,8 @@ typedef struct {
bool ssid_found : 1;
bool hidden_probe_scan_warn : 1;
+ bool addressing_running_indicated : 1;
+
} NMDeviceWifiPrivate;
struct _NMDeviceWifi {
@@ -394,6 +395,22 @@ nm_device_wifi_scanning_prohibited_track(NMDeviceWifi *self,
/*****************************************************************************/
static void
+_indicate_addressing_running_reset(NMDeviceWifi *self)
+{
+ NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self);
+
+ if (!priv->addressing_running_indicated)
+ return;
+
+ priv->addressing_running_indicated = FALSE;
+ nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(NM_DEVICE(self)),
+ nm_device_get_ifindex(NM_DEVICE(self)),
+ FALSE);
+}
+
+/*****************************************************************************/
+
+static void
_ap_dump(NMDeviceWifi * self,
NMLogLevel log_level,
const NMWifiAP *ap,
@@ -932,8 +949,7 @@ deactivate(NMDevice *device)
if (!wake_on_wlan_restore(self))
_LOGW(LOGD_DEVICE | LOGD_WIFI, "Cannot unconfigure WoWLAN.");
- /* Clear any critical protocol notification in the Wi-Fi stack */
- nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device), ifindex, FALSE);
+ _indicate_addressing_running_reset(self);
/* Ensure we're in infrastructure mode after deactivation; some devices
* (usually older ones) don't scan well in adhoc mode.
@@ -2478,7 +2494,7 @@ supplicant_iface_state(NMDeviceWifi * self,
priv->mode == _NM_802_11_MODE_AP ? "Started Wi-Fi Hotspot"
: "Connected to wireless network",
(ssid_str = _nm_utils_ssid_to_string_gbytes(ssid)));
- nm_device_activate_schedule_stage3_ip_config_start(device);
+ nm_device_activate_schedule_stage3_ip_config(device, FALSE);
} else if (devstate == NM_DEVICE_STATE_ACTIVATED)
periodic_update(self);
break;
@@ -3263,20 +3279,24 @@ out_fail:
return NM_ACT_STAGE_RETURN_FAILURE;
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
{
- gboolean indicate_addressing_running;
- NMConnection *connection;
- const char * method;
+ NMDeviceWifi * self = NM_DEVICE_WIFI(device);
+ NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self);
+ const char * method;
+ gboolean indicate_addressing_running;
+
+ if (priv->addressing_running_indicated)
+ return;
- connection = nm_device_get_applied_connection(device);
+ /* we always set the flag, even if we don't indicate it below. The reason
+ * is that we always want to *clear* the flag after we are done (as we don't
+ * know whether it isn't already set on the interface). */
+ priv->addressing_running_indicated = TRUE;
- method = nm_utils_get_ip_config_method(connection, addr_family);
- if (addr_family == AF_INET)
+ method = nm_utils_get_ip_config_method(nm_device_get_applied_connection(device), addr_family);
+ if (NM_IS_IPv4(addr_family))
indicate_addressing_running = NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
else {
indicate_addressing_running = NM_IN_STRSET(method,
@@ -3284,13 +3304,11 @@ act_stage3_ip_config_start(NMDevice * device,
NM_SETTING_IP6_CONFIG_METHOD_DHCP);
}
- if (indicate_addressing_running)
+ if (indicate_addressing_running) {
nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device),
nm_device_get_ip_ifindex(device),
TRUE);
-
- return NM_DEVICE_CLASS(nm_device_wifi_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ }
}
static guint32
@@ -3301,77 +3319,6 @@ get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *ou
out_source);
}
-static gboolean
-is_static_wep(NMConnection *connection)
-{
- NMSettingWirelessSecurity *s_wsec;
- const char * str;
-
- g_return_val_if_fail(connection != NULL, FALSE);
-
- s_wsec = nm_connection_get_setting_wireless_security(connection);
- if (!s_wsec)
- return FALSE;
-
- str = nm_setting_wireless_security_get_key_mgmt(s_wsec);
- if (g_strcmp0(str, "none") != 0)
- return FALSE;
-
- str = nm_setting_wireless_security_get_auth_alg(s_wsec);
- if (g_strcmp0(str, "leap") == 0)
- return FALSE;
-
- return TRUE;
-}
-
-static NMActStageReturn
-act_stage4_ip_config_timeout(NMDevice * device,
- int addr_family,
- NMDeviceStateReason *out_failure_reason)
-{
- NMDeviceWifi * self = NM_DEVICE_WIFI(device);
- NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self);
- NMConnection * connection;
- NMSettingIPConfig * s_ip;
- gboolean may_fail;
-
- connection = nm_device_get_applied_connection(device);
- s_ip = nm_connection_get_setting_ip_config(connection, addr_family);
- may_fail = nm_setting_ip_config_get_may_fail(s_ip);
-
- if (priv->mode == _NM_802_11_MODE_AP)
- goto call_parent;
-
- if (may_fail || !is_static_wep(connection)) {
- /* Not static WEP or failure allowed; let superclass handle it */
- goto call_parent;
- }
-
- /* If IP configuration times out and it's a static WEP connection, that
- * usually means the WEP key is wrong. WEP's Open System auth mode has
- * no provision for figuring out if the WEP key is wrong, so you just have
- * to wait for DHCP to fail to figure it out. For all other Wi-Fi security
- * types (open, WPA, 802.1x, etc) if the secrets/certs were wrong the
- * connection would have failed before IP configuration.
- *
- * Activation failed, we must have bad encryption key */
- _LOGW(LOGD_DEVICE | LOGD_WIFI,
- "Activation: (wifi) could not get IP configuration for connection '%s'.",
- nm_connection_get_id(connection));
-
- if (!handle_auth_or_fail(self, NULL, TRUE)) {
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_NO_SECRETS);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
-
- _LOGI(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) asking for new secrets");
- return NM_ACT_STAGE_RETURN_POSTPONE;
-
-call_parent:
- return NM_DEVICE_CLASS(nm_device_wifi_parent_class)
- ->act_stage4_ip_config_timeout(device, addr_family, out_failure_reason);
-}
-
static void
activation_success_handler(NMDevice *device)
{
@@ -3383,8 +3330,7 @@ activation_success_handler(NMDevice *device)
req = nm_device_get_act_request(device);
g_assert(req);
- /* Clear any critical protocol notification in the wifi stack */
- nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device), ifindex, FALSE);
+ _indicate_addressing_running_reset(self);
/* There should always be a current AP, either a fake one because we haven't
* seen a scan result for the activated AP yet, or a real one from the
@@ -3484,19 +3430,13 @@ device_state_changed(NMDevice * device,
nm_supplicant_interface_disconnect(priv->sup_iface);
break;
case NM_DEVICE_STATE_IP_CHECK:
- /* Clear any critical protocol notification in the wifi stack */
- nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device),
- nm_device_get_ifindex(device),
- FALSE);
+ _indicate_addressing_running_reset(self);
break;
case NM_DEVICE_STATE_ACTIVATED:
activation_success_handler(device);
break;
case NM_DEVICE_STATE_FAILED:
- /* Clear any critical protocol notification in the wifi stack */
- nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device),
- nm_device_get_ifindex(device),
- FALSE);
+ _indicate_addressing_running_reset(self);
break;
case NM_DEVICE_STATE_DISCONNECTED:
break;
@@ -3803,17 +3743,16 @@ nm_device_wifi_class_init(NMDeviceWifiClass *klass)
device_class->get_guessed_metered = get_guessed_metered;
device_class->set_enabled = set_enabled;
- device_class->act_stage1_prepare = act_stage1_prepare;
- device_class->act_stage2_config = act_stage2_config;
- device_class->get_configured_mtu = get_configured_mtu;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
- device_class->act_stage4_ip_config_timeout = act_stage4_ip_config_timeout;
- device_class->deactivate_async = deactivate_async;
- device_class->deactivate = deactivate;
- device_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr;
- device_class->unmanaged_on_quit = unmanaged_on_quit;
- device_class->can_reapply_change = can_reapply_change;
- device_class->reapply_connection = reapply_connection;
+ device_class->act_stage1_prepare = act_stage1_prepare;
+ device_class->act_stage2_config = act_stage2_config;
+ device_class->get_configured_mtu = get_configured_mtu;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
+ device_class->deactivate_async = deactivate_async;
+ device_class->deactivate = deactivate;
+ device_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr;
+ device_class->unmanaged_on_quit = unmanaged_on_quit;
+ device_class->can_reapply_change = can_reapply_change;
+ device_class->reapply_connection = reapply_connection;
device_class->state_changed = device_state_changed;
diff --git a/src/core/devices/wwan/libnm-wwan.ver b/src/core/devices/wwan/libnm-wwan.ver
index c368a5907d..230f515faa 100644
--- a/src/core/devices/wwan/libnm-wwan.ver
+++ b/src/core/devices/wwan/libnm-wwan.ver
@@ -14,7 +14,6 @@ global:
nm_modem_get_control_port;
nm_modem_get_device_id;
nm_modem_get_driver;
- nm_modem_get_iid;
nm_modem_get_ip_ifindex;
nm_modem_get_operator_code;
nm_modem_get_path;
diff --git a/src/core/devices/wwan/nm-device-modem.c b/src/core/devices/wwan/nm-device-modem.c
index 1b28546937..ff51855c00 100644
--- a/src/core/devices/wwan/nm-device-modem.c
+++ b/src/core/devices/wwan/nm-device-modem.c
@@ -8,7 +8,7 @@
#include "nm-device-modem.h"
#include "nm-modem.h"
-#include "nm-ip4-config.h"
+#include "nm-l3-config-data.h"
#include "devices/nm-device-private.h"
#include "nm-rfkill-manager.h"
#include "settings/nm-settings-connection.h"
@@ -33,6 +33,7 @@ typedef struct {
NMModem * modem;
NMDeviceModemCapabilities caps;
NMDeviceModemCapabilities current_caps;
+ NMUtilsIPv6IfaceId iid;
char * device_id;
char * operator_code;
char * apn;
@@ -73,26 +74,29 @@ ppp_failed(NMModem *modem, guint i_reason, gpointer user_data)
case NM_DEVICE_STATE_IP_CHECK:
case NM_DEVICE_STATE_SECONDARIES:
case NM_DEVICE_STATE_ACTIVATED:
- if (nm_device_activate_ip4_state_in_conf(device))
- nm_device_activate_schedule_ip_config_timeout(device, AF_INET);
- else if (nm_device_activate_ip6_state_in_conf(device))
- nm_device_activate_schedule_ip_config_timeout(device, AF_INET6);
- else if (nm_device_activate_ip4_state_done(device)) {
- nm_device_ip_method_failed(device,
- AF_INET,
- NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- } else if (nm_device_activate_ip6_state_done(device)) {
- nm_device_ip_method_failed(device,
- AF_INET6,
- NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- } else {
- _LOGW(LOGD_MB,
- "PPP failure in unexpected state %u",
- (guint) nm_device_get_state(device));
- nm_device_state_changed(device,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- }
+ /* FIXME(l3cfg): this is not right. We don't control the IP state
+ * from the subclass this way. */
+ (void) self;
+ //if (nm_device_activate_get_ip_state(device, AF_INET) == NM_DEVICE_IP_STATE_PENDING)
+ // nm_device_activate_schedule_ip_config_timeout(device, AF_INET);
+ //else if (nm_device_activate_get_ip_state(device, AF_INET6) == NM_DEVICE_IP_STATE_PENDING)
+ // nm_device_activate_schedule_ip_config_timeout(device, AF_INET6);
+ //else if (nm_device_activate_get_ip_state(device, AF_INET) == NM_DEVICE_IP_STATE_READY) {
+ // nm_device_dev_ip_method_failed(device,
+ // AF_INET,
+ // NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ //} else if (nm_device_activate_get_ip_state(device, AF_INET6) == NM_DEVICE_IP_STATE_READY) {
+ // nm_device_dev_ip_method_failed(device,
+ // AF_INET6,
+ // NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ //} else {
+ // _LOGW(LOGD_MB,
+ // "PPP failure in unexpected state %u",
+ // (guint) nm_device_get_state(device));
+ // nm_device_state_changed(device,
+ // NM_DEVICE_STATE_FAILED,
+ // NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ //}
break;
default:
break;
@@ -188,42 +192,42 @@ modem_auth_result(NMModem *modem, GError *error, gpointer user_data)
}
static void
-modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpointer user_data)
-{
- NMDeviceModem *self = NM_DEVICE_MODEM(user_data);
- NMDevice * device = NM_DEVICE(self);
+modem_new_config(NMModem * modem,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ gboolean do_slaac,
+ const NMUtilsIPv6IfaceId *iid,
+ GError * error,
+ gpointer user_data)
+{
+#if 0
+ NMDeviceModem * self = NM_DEVICE_MODEM(user_data);
+ NMDeviceModemPrivate * priv = NM_DEVICE_MODEM_GET_PRIVATE(self);
+ NMDevice * device = NM_DEVICE(self);
+ NMActStageReturn ret;
+ NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_ignored = NULL;
+
+ /* FIXME(l3cfg): this is not the right way to handle IP state anymore. */
+
+ if (addr_family == AF_INET) {
+ g_return_if_fail(nm_device_activate_get_ip_state(device, AF_INET)
+ == NM_DEVICE_IP_STATE_PENDING);
- if (!nm_device_activate_ip4_state_in_conf(device)) {
- _LOGD(LOGD_MB | LOGD_IP4,
- "retrieving IPv4 configuration while no longer in state IPv4 conf");
- return;
- }
+ if (error) {
+ _LOGW(LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message);
+ nm_device_dev_ip_method_failed(device,
+ AF_INET,
+ NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ return;
+ }
- if (error) {
- _LOGW(LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message);
- nm_device_ip_method_failed(device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET);
return;
}
- nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG_CAST(config));
- nm_device_activate_schedule_ip_config_result(device, AF_INET, NULL);
-}
-
-static void
-modem_ip6_config_result(NMModem * modem,
- NMIP6Config *config,
- gboolean do_slaac,
- GError * error,
- gpointer user_data)
-{
- NMDeviceModem * self = NM_DEVICE_MODEM(user_data);
- NMDevice * device = NM_DEVICE(self);
- NMActStageReturn ret;
- NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
- gs_unref_object NMIP6Config *ignored = NULL;
- gboolean got_config = !!config;
-
- if (!nm_device_activate_ip6_state_in_conf(device)) {
+ if (nm_device_activate_get_ip_state(device, AF_INET6) != NM_DEVICE_IP_STATE_PENDING) {
_LOGD(LOGD_MB | LOGD_IP6,
"retrieving IPv6 configuration while no longer in state IPv6 conf");
return;
@@ -231,43 +235,48 @@ modem_ip6_config_result(NMModem * modem,
if (error) {
_LOGW(LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", error->message);
- nm_device_ip_method_failed(device, AF_INET6, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ nm_device_dev_ip_method_failed(device,
+ AF_INET6,
+ NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
return;
}
+ if (iid)
+ priv->iid = *iid;
+ else
+ priv->iid.id = 0;
+
/* Re-enable IPv6 on the interface */
nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "0");
- if (config)
- nm_device_set_dev2_ip_config(device, AF_INET6, NM_IP_CONFIG_CAST(config));
+ nm_device_set_dev2_ip_config(device, AF_INET6, l3cd);
if (do_slaac == FALSE) {
- if (got_config)
- nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL);
+ if (l3cd)
+ nm_device_activate_schedule_ip_config_result(device, AF_INET6);
else {
_LOGW(LOGD_MB | LOGD_IP6,
"retrieving IPv6 configuration failed: SLAAC not requested and no addresses");
- nm_device_ip_method_failed(device,
- AF_INET6,
- NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ nm_device_dev_ip_method_failed(device,
+ AF_INET6,
+ NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
}
return;
}
/* Start SLAAC now that we have a link-local address from the modem */
- ret =
- NM_DEVICE_CLASS(nm_device_modem_parent_class)
- ->act_stage3_ip_config_start(device, AF_INET6, (gpointer *) &ignored, &failure_reason);
+ ret = NM_DEVICE_CLASS(nm_device_modem_parent_class)
+ ->act_stage3_ip_config(device, AF_INET6, &l3cd_ignored, &failure_reason);
- nm_assert(ignored == NULL);
+ nm_assert(!l3cd_ignored);
switch (ret) {
case NM_ACT_STAGE_RETURN_FAILURE:
- nm_device_ip_method_failed(device, AF_INET6, failure_reason);
+ nm_device_dev_ip_method_failed(device, AF_INET6, failure_reason);
break;
case NM_ACT_STAGE_RETURN_IP_FAIL:
/* all done */
- nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET6);
break;
case NM_ACT_STAGE_RETURN_POSTPONE:
/* let SLAAC run */
@@ -278,6 +287,7 @@ modem_ip6_config_result(NMModem * modem,
*/
nm_assert_not_reached();
}
+#endif
}
static void
@@ -610,47 +620,50 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
return NM_ACT_STAGE_RETURN_SUCCESS;
}
-static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
{
- NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device);
- gboolean autoip4 = FALSE;
- NMActStageReturn ret;
+ NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device);
- if (!NM_IS_IPv4(addr_family))
- return nm_modem_stage3_ip6_config_start(priv->modem, device, out_failure_reason);
+ XXX("fix implementation");
+ if (!NM_IS_IPv4(addr_family)) {
+ nm_modem_stage3_ip6_config_start(priv->modem, device, NULL);
+ return;
+ }
+
+ //XXX
+#if 0
ret = nm_modem_stage3_ip4_config_start(priv->modem, device, &autoip4, out_failure_reason);
if (ret != NM_ACT_STAGE_RETURN_SUCCESS || !autoip4)
return ret;
return NM_DEVICE_CLASS(nm_device_modem_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ ->act_stage3_ip_config(device, addr_family, out_config, out_failure_reason);
+#endif
}
-static void
-ip4_config_pre_commit(NMDevice *device, NMIP4Config *config)
-{
- nm_modem_ip4_pre_commit(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, device, config);
-}
+//XXX static void
+//XXX ip4_config_pre_commit(NMDevice *device)
+//XXX {
+//XXX nm_modem_ip4_pre_commit(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, device);
+//XXX }
static gboolean
get_ip_iface_identifier(NMDevice *device, NMUtilsIPv6IfaceId *out_iid)
{
NMDeviceModem * self = NM_DEVICE_MODEM(device);
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self);
- gboolean success;
g_return_val_if_fail(priv->modem, FALSE);
- success = nm_modem_get_iid(priv->modem, out_iid);
- if (!success)
- success =
- NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_ip_iface_identifier(device, out_iid);
- return success;
+
+ if (priv->iid.id != 0) {
+ *out_iid = priv->iid;
+ return TRUE;
+ }
+
+ return NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_ip_iface_identifier(device, out_iid);
}
/*****************************************************************************/
@@ -716,8 +729,7 @@ set_modem(NMDeviceModem *self, NMModem *modem)
g_signal_connect(modem, NM_MODEM_PPP_FAILED, G_CALLBACK(ppp_failed), self);
g_signal_connect(modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK(modem_prepare_result), self);
- g_signal_connect(modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK(modem_ip4_config_result), self);
- g_signal_connect(modem, NM_MODEM_IP6_CONFIG_RESULT, G_CALLBACK(modem_ip6_config_result), self);
+ g_signal_connect(modem, NM_MODEM_NEW_CONFIG, G_CALLBACK(modem_new_config), self);
g_signal_connect(modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK(modem_auth_requested), self);
g_signal_connect(modem, NM_MODEM_AUTH_RESULT, G_CALLBACK(modem_auth_result), self);
g_signal_connect(modem, NM_MODEM_STATE_CHANGED, G_CALLBACK(modem_state_cb), self);
@@ -904,8 +916,8 @@ nm_device_modem_class_init(NMDeviceModemClass *klass)
device_class->deactivate = deactivate;
device_class->act_stage1_prepare = act_stage1_prepare;
device_class->act_stage2_config = act_stage2_config;
- device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
- device_class->ip4_config_pre_commit = ip4_config_pre_commit;
+ device_class->act_stage3_ip_config = act_stage3_ip_config;
+ //XXX device_class->ip4_config_pre_commit = ip4_config_pre_commit;
device_class->get_enabled = get_enabled;
device_class->set_enabled = set_enabled;
device_class->owns_iface = owns_iface;
diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c
index a5139f0833..cdd3a1089f 100644
--- a/src/core/devices/wwan/nm-modem-broadband.c
+++ b/src/core/devices/wwan/nm-modem-broadband.c
@@ -16,8 +16,7 @@
#include "NetworkManagerUtils.h"
#include "devices/nm-device-private.h"
#include "libnm-platform/nm-platform.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "nm-l3-config-data.h"
#define NM_MODEM_BROADBAND_MODEM "modem"
@@ -961,21 +960,23 @@ set_mm_enabled(NMModem *_self, gboolean enabled)
/* IPv4 method static */
static gboolean
-static_stage3_ip4_done(NMModemBroadband *self)
+static_stage3_ip4_done(gpointer user_data)
{
- GError * error = NULL;
- gs_unref_object NMIP4Config *config = NULL;
- const char * data_port;
- const char * address_string;
- const char * gw_string;
- guint32 address_network;
- guint32 gw = 0;
- NMPlatformIP4Address address;
- const char ** dns;
- guint i;
- guint32 ip4_route_table, ip4_route_metric;
- NMPlatformIP4Route * r;
- guint32 mtu_n;
+ NMModemBroadband * self = user_data;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ char sbuf[sizeof(_nm_utils_to_string_buffer)];
+ gs_free_error GError *error = NULL;
+ const char * data_port;
+ const char * address_string;
+ const char * gw_string;
+ guint32 address_network;
+ guint32 gw = 0;
+ NMPlatformIP4Address address;
+ const char ** dns;
+ int ifindex;
+ guint i;
+ NMPlatformIP4Route route;
+ guint32 mtu_n;
g_return_val_if_fail(self->_priv.ipv4_config, FALSE);
g_return_val_if_fail(self->_priv.bearer, FALSE);
@@ -988,58 +989,72 @@ static_stage3_ip4_done(NMModemBroadband *self)
address_string = mm_bearer_ip_config_get_address(self->_priv.ipv4_config);
if (!address_string
|| !nm_utils_parse_inaddr_bin(AF_INET, address_string, NULL, &address_network)) {
- error =
- g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IP4 configuration failed: invalid address given %s%s%s",
- nm_modem_get_uid(NM_MODEM(self)),
- NM_PRINT_FMT_QUOTE_STRING(address_string));
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IP4 configuration failed: invalid address given %s%s%s",
+ nm_modem_get_uid(NM_MODEM(self)),
+ NM_PRINT_FMT_QUOTE_STRING(address_string));
goto out;
}
/* Missing gateway not a hard failure */
gw_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv4_config);
if (gw_string && !nm_utils_parse_inaddr_bin(AF_INET, gw_string, NULL, &gw)) {
- error =
- g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IP4 configuration failed: invalid gateway address \"%s\"",
- nm_modem_get_uid(NM_MODEM(self)),
- gw_string);
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IP4 configuration failed: invalid gateway address \"%s\"",
+ nm_modem_get_uid(NM_MODEM(self)),
+ gw_string);
goto out;
}
data_port = mm_bearer_get_interface(self->_priv.bearer);
g_return_val_if_fail(data_port, FALSE);
- config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
- nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port));
-
- 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.addr_source = NM_IP_CONFIG_SOURCE_WWAN;
+
+ ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port);
+ if (ifindex <= 0) {
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) data port %s not found",
+ nm_modem_get_uid(NM_MODEM(self)),
+ data_port);
+ goto out;
+ }
+
+ l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
+ ifindex,
+ NM_IP_CONFIG_SOURCE_WWAN);
+
+ address = (NMPlatformIP4Address){
+ .address = address_network,
+ .peer_address = address_network,
+ .plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv4_config),
+ .addr_source = NM_IP_CONFIG_SOURCE_WWAN,
+ };
if (address.plen <= 32)
- nm_ip4_config_add_address(config, &address);
+ nm_l3_config_data_add_address_4(l3cd, &address);
- _LOGI(" address %s/%d", address_string, address.plen);
+ _LOGI(" address %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf)));
- nm_modem_get_route_parameters(NM_MODEM(self), &ip4_route_table, &ip4_route_metric, NULL, NULL);
- r = &(NMPlatformIP4Route){
+ route = (NMPlatformIP4Route){
.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
.gateway = gw,
- .table_coerced = nm_platform_route_table_coerce(ip4_route_table),
- .metric = ip4_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
- nm_ip4_config_add_route(config, r, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &route);
_LOGI(" gateway %s", gw_string);
- /* DNS servers */
dns = mm_bearer_ip_config_get_dns(self->_priv.ipv4_config);
for (i = 0; dns && dns[i]; i++) {
if (nm_utils_parse_inaddr_bin(AF_INET, dns[i], NULL, &address_network)
&& address_network > 0) {
- nm_ip4_config_add_nameserver(config, address_network);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &address_network);
_LOGI(" DNS %s", dns[i]);
}
}
@@ -1047,15 +1062,17 @@ static_stage3_ip4_done(NMModemBroadband *self)
#if MM_CHECK_VERSION(1, 4, 0)
mtu_n = mm_bearer_ip_config_get_mtu(self->_priv.ipv4_config);
if (mtu_n) {
- nm_ip4_config_set_mtu(config, mtu_n, NM_IP_CONFIG_SOURCE_WWAN);
+ nm_l3_config_data_set_mtu(l3cd, mtu_n);
_LOGI(" MTU %u", mtu_n);
}
#endif
out:
- g_signal_emit_by_name(self, NM_MODEM_IP4_CONFIG_RESULT, config, error);
- g_clear_error(&error);
- return FALSE;
+ if (error)
+ nm_clear_l3cd(&l3cd);
+
+ nm_modem_emit_signal_new_config(NM_MODEM(self), AF_INET, l3cd, FALSE, NULL, error);
+ return G_SOURCE_REMOVE;
}
static NMActStageReturn
@@ -1069,8 +1086,7 @@ static_stage3_ip4_config_start(NMModem * modem,
/* We schedule it in an idle just to follow the same logic as in the
* generic modem implementation. */
nm_clear_g_source(&priv->idle_id_ip4);
- priv->idle_id_ip4 = g_idle_add((GSourceFunc) static_stage3_ip4_done, self);
-
+ priv->idle_id_ip4 = g_idle_add(static_stage3_ip4_done, self);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
@@ -1078,21 +1094,26 @@ static_stage3_ip4_config_start(NMModem * modem,
/* IPv6 method static */
static gboolean
-stage3_ip6_done(NMModemBroadband *self)
+stage3_ip6_done(gpointer user_data)
{
- GError * error = NULL;
- NMIP6Config * config = NULL;
- const char * data_port;
- const char * address_string;
- NMPlatformIP6Address address;
- NMModemIPMethod ip_method;
- const char ** dns;
- guint i;
-
- g_return_val_if_fail(self->_priv.ipv6_config, FALSE);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ char sbuf[sizeof(_nm_utils_to_string_buffer)];
+ NMModemBroadband * self = user_data;
+ gs_free_error GError * error = NULL;
+ const char * data_port;
+ const char * address_string;
+ NMPlatformIP6Address address;
+ NMModemIPMethod ip_method;
+ const char ** dns;
+ guint i;
+ gboolean do_slaac = TRUE;
+ int ifindex;
+ NMUtilsIPv6IfaceId iid_data;
+ const NMUtilsIPv6IfaceId *iid = NULL;
+
+ g_return_val_if_fail(self->_priv.ipv6_config, G_SOURCE_REMOVE);
self->_priv.idle_id_ip6 = 0;
- memset(&address, 0, sizeof(address));
ip_method = get_bearer_ip_method(self->_priv.ipv6_config);
@@ -1100,93 +1121,114 @@ stage3_ip6_done(NMModemBroadband *self)
if (!address_string) {
/* DHCP/SLAAC is allowed to skip addresses; other methods require it */
if (ip_method != NM_MODEM_IP_METHOD_AUTO) {
- error = g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IPv6 configuration failed: no address given",
- nm_modem_get_uid(NM_MODEM(self)));
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IPv6 configuration failed: no address given",
+ nm_modem_get_uid(NM_MODEM(self)));
}
goto out;
}
- /* Fail if invalid IP address retrieved */
- if (!inet_pton(AF_INET6, address_string, (void *) &(address.address))) {
- error = g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IPv6 configuration failed: invalid address given '%s'",
- nm_modem_get_uid(NM_MODEM(self)),
- address_string);
+ address = (NMPlatformIP6Address){};
+
+ if (!inet_pton(AF_INET6, address_string, &address.address)) {
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IPv6 configuration failed: invalid address given '%s'",
+ nm_modem_get_uid(NM_MODEM(self)),
+ address_string);
goto out;
}
- _LOGI("IPv6 base configuration:");
-
data_port = mm_bearer_get_interface(self->_priv.bearer);
- g_return_val_if_fail(data_port, FALSE);
+ g_return_val_if_fail(data_port, G_SOURCE_REMOVE);
+
+ ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port);
+ if (ifindex <= 0) {
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) data port %s not found",
+ nm_modem_get_uid(NM_MODEM(self)),
+ data_port);
+ goto out;
+ }
+
+ _LOGI("IPv6 base configuration:");
- config = nm_ip6_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
- nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port));
+ l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
+ ifindex,
+ NM_IP_CONFIG_SOURCE_WWAN);
address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv6_config);
- if (address.plen <= 128)
- nm_ip6_config_add_address(config, &address);
+ if (address.plen <= 128) {
+ if (IN6_IS_ADDR_LINKLOCAL(&address.address)) {
+ iid_data.id = ((guint64 *) (&address.address.s6_addr))[1];
+ iid = &iid_data;
+ } else
+ do_slaac = FALSE;
+ nm_l3_config_data_add_address_6(l3cd, &address);
+ }
- _LOGI(" address %s/%d", address_string, address.plen);
+ _LOGI(" address %s (slaac %s)",
+ nm_platform_ip6_address_to_string(&address, sbuf, sizeof(sbuf)),
+ do_slaac ? "enabled" : "disabled");
address_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv6_config);
if (address_string) {
- guint32 ip6_route_table, ip6_route_metric;
-
if (inet_pton(AF_INET6, address_string, &address.address) != 1) {
- error =
- g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IPv6 configuration failed: invalid gateway given '%s'",
- nm_modem_get_uid(NM_MODEM(self)),
- address_string);
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IPv6 configuration failed: invalid gateway given '%s'",
+ nm_modem_get_uid(NM_MODEM(self)),
+ address_string);
goto out;
}
- nm_modem_get_route_parameters(NM_MODEM(self),
- NULL,
- NULL,
- &ip6_route_table,
- &ip6_route_metric);
{
const NMPlatformIP6Route r = {
.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
.gateway = address.address,
- .table_coerced = nm_platform_route_table_coerce(ip6_route_table),
- .metric = ip6_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
_LOGI(" gateway %s", address_string);
- nm_ip6_config_add_route(config, &r, NULL);
+ nm_l3_config_data_add_route_6(l3cd, &r);
}
} else if (ip_method == NM_MODEM_IP_METHOD_STATIC) {
/* Gateway required for the 'static' method */
- error = g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IPv6 configuration failed: missing gateway",
- nm_modem_get_uid(NM_MODEM(self)));
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IPv6 configuration failed: missing gateway",
+ nm_modem_get_uid(NM_MODEM(self)));
goto out;
}
- /* DNS servers */
dns = mm_bearer_ip_config_get_dns(self->_priv.ipv6_config);
for (i = 0; dns && dns[i]; i++) {
struct in6_addr addr;
if (inet_pton(AF_INET6, dns[i], &addr)) {
- nm_ip6_config_add_nameserver(config, &addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &addr);
_LOGI(" DNS %s", dns[i]);
}
}
out:
- nm_modem_emit_ip6_config_result(NM_MODEM(self), config, error);
- g_clear_object(&config);
- g_clear_error(&error);
- return FALSE;
+ if (error) {
+ nm_clear_l3cd(&l3cd);
+ do_slaac = FALSE;
+ iid = NULL;
+ }
+ nm_modem_emit_signal_new_config(NM_MODEM(self), AF_INET6, l3cd, do_slaac, iid, error);
+ return G_SOURCE_REMOVE;
}
static NMActStageReturn
@@ -1198,7 +1240,7 @@ stage3_ip6_config_request(NMModem *modem, NMDeviceStateReason *out_failure_reaso
/* We schedule it in an idle just to follow the same logic as in the
* generic modem implementation. */
nm_clear_g_source(&priv->idle_id_ip6);
- priv->idle_id_ip6 = g_idle_add((GSourceFunc) stage3_ip6_done, self);
+ priv->idle_id_ip6 = g_idle_add(stage3_ip6_done, self);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c
index 78ad7b6820..30c910af54 100644
--- a/src/core/devices/wwan/nm-modem-ofono.c
+++ b/src/core/devices/wwan/nm-modem-ofono.c
@@ -11,7 +11,7 @@
#include "devices/nm-device-private.h"
#include "nm-modem.h"
#include "libnm-platform/nm-platform.h"
-#include "nm-ip4-config.h"
+#include "nm-l3-config-data.h"
#define VARIANT_IS_OF_TYPE_BOOLEAN(v) \
((v) != NULL && (g_variant_is_of_type((v), G_VARIANT_TYPE_BOOLEAN)))
@@ -47,7 +47,7 @@ typedef struct {
gboolean modem_online;
gboolean gprs_attached;
- NMIP4Config *ip4_config;
+ NML3ConfigData *l3cd_4;
} NMModemOfonoPrivate;
struct _NMModemOfono {
@@ -240,7 +240,7 @@ deactivate_cleanup(NMModem *modem, NMDevice *device, gboolean stop_ppp_manager)
/* TODO: cancel SimpleConnect() if any */
- g_clear_object(&priv->ip4_config);
+ nm_clear_l3cd(&priv->l3cd_4);
NM_MODEM_CLASS(nm_modem_ofono_parent_class)
->deactivate_cleanup(modem, device, stop_ppp_manager);
@@ -734,13 +734,13 @@ handle_settings(GVariant *v_dict, gpointer user_data)
{
NMModemOfono * self = NM_MODEM_OFONO(user_data);
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
- NMPlatformIP4Address addr;
+ char sbuf[sizeof(_nm_utils_to_string_buffer)];
+ NMPlatformIP4Address address;
gboolean ret = FALSE;
const char * interface;
const char * s;
- const char ** array, **iter;
+ const char ** array;
guint32 address_network, gateway_network;
- guint32 ip4_route_table, ip4_route_metric;
int ifindex;
GError * error = NULL;
@@ -773,12 +773,14 @@ handle_settings(GVariant *v_dict, gpointer user_data)
}
ifindex = nm_modem_get_ip_ifindex(NM_MODEM(self));
- nm_assert(ifindex > 0);
+ g_return_if_fail(ifindex > 0);
- /* TODO: verify handling of ip4_config; check other places it's used... */
- g_clear_object(&priv->ip4_config);
+ /* TODO: verify handling of l3cd_4; check other places it's used... */
+ nm_clear_l3cd(&priv->l3cd_4);
- priv->ip4_config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), ifindex);
+ priv->l3cd_4 = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
+ ifindex,
+ NM_IP_CONFIG_SOURCE_WWAN);
if (!g_variant_lookup(v_dict, "Address", "&s", &s)) {
_LOGW("Settings 'Address' missing");
@@ -788,10 +790,12 @@ handle_settings(GVariant *v_dict, gpointer user_data)
_LOGW("can't convert 'Address' %s to addr", s ?: "");
goto out;
}
- memset(&addr, 0, sizeof(addr));
- addr.ifindex = ifindex;
- addr.address = address_network;
- addr.addr_source = NM_IP_CONFIG_SOURCE_WWAN;
+
+ address = (NMPlatformIP4Address){
+ .ifindex = ifindex,
+ .address = address_network,
+ .addr_source = NM_IP_CONFIG_SOURCE_WWAN,
+ };
if (!g_variant_lookup(v_dict, "Netmask", "&s", &s)) {
_LOGW("Settings 'Netmask' missing");
@@ -801,10 +805,10 @@ handle_settings(GVariant *v_dict, gpointer user_data)
_LOGW("invalid 'Netmask': %s", s ?: "");
goto out;
}
- addr.plen = nm_utils_ip4_netmask_to_prefix(address_network);
+ address.plen = nm_utils_ip4_netmask_to_prefix(address_network);
- _LOGI("Address: %s", nm_platform_ip4_address_to_string(&addr, NULL, 0));
- nm_ip4_config_add_address(priv->ip4_config, &addr);
+ _LOGI("Address: %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf)));
+ nm_l3_config_data_add_address_4(priv->l3cd_4, &address);
if (!g_variant_lookup(v_dict, "Gateway", "&s", &s) || !s) {
_LOGW("Settings 'Gateway' missing");
@@ -814,17 +818,18 @@ handle_settings(GVariant *v_dict, gpointer user_data)
_LOGW("invalid 'Gateway': %s", s);
goto out;
}
- nm_modem_get_route_parameters(NM_MODEM(self), &ip4_route_table, &ip4_route_metric, NULL, NULL);
{
const NMPlatformIP4Route r = {
.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
.gateway = gateway_network,
- .table_coerced = nm_platform_route_table_coerce(ip4_route_table),
- .metric = ip4_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
_LOGI("Gateway: %s", s);
- nm_ip4_config_add_route(priv->ip4_config, &r, NULL);
+ nm_l3_config_data_add_route_4(priv->l3cd_4, &r);
}
if (!g_variant_lookup(v_dict, "DomainNameServers", "^a&s", &array)) {
@@ -832,52 +837,49 @@ handle_settings(GVariant *v_dict, gpointer user_data)
goto out;
}
if (array) {
- for (iter = array; *iter; iter++) {
- if (nm_utils_parse_inaddr_bin(AF_INET, *iter, NULL, &address_network)
- && address_network) {
- _LOGI("DNS: %s", *iter);
- nm_ip4_config_add_nameserver(priv->ip4_config, address_network);
- } else {
- _LOGW("invalid NameServer: %s", *iter);
+ gs_free const char **array_free = array;
+ gboolean any_good = FALSE;
+
+ for (; array[0]; array++) {
+ if (!nm_utils_parse_inaddr_bin(AF_INET, *array, NULL, &address_network)
+ || !address_network) {
+ _LOGW("invalid NameServer: %s", *array);
+ continue;
}
+ any_good = TRUE;
+ _LOGI("DNS: %s", *array);
+ nm_l3_config_data_add_nameserver(priv->l3cd_4, AF_INET, &address_network);
}
-
- if (iter == array) {
+ if (!any_good) {
_LOGW("Settings: 'DomainNameServers': none specified");
- g_free(array);
goto out;
}
- g_free(array);
}
if (g_variant_lookup(v_dict, "MessageProxy", "&s", &s)) {
_LOGI("MessageProxy: %s", s);
if (s && nm_utils_parse_inaddr_bin(AF_INET, s, NULL, &address_network)) {
- nm_modem_get_route_parameters(NM_MODEM(self),
- &ip4_route_table,
- &ip4_route_metric,
- NULL,
- NULL);
-
- {
- const NMPlatformIP4Route mms_route = {
- .network = address_network,
- .plen = 32,
- .gateway = gateway_network,
- .table_coerced = nm_platform_route_table_coerce(ip4_route_table),
- .metric = ip4_route_metric,
- };
-
- nm_ip4_config_add_route(priv->ip4_config, &mms_route, NULL);
- }
- } else {
+ const NMPlatformIP4Route mms_route = {
+ .network = address_network,
+ .plen = 32,
+ .gateway = gateway_network,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
+ };
+
+ nm_l3_config_data_add_route_4(priv->l3cd_4, &mms_route);
+ } else
_LOGW("invalid MessageProxy: %s", s);
- }
}
ret = TRUE;
out:
+ if (priv->l3cd_4)
+ nm_l3_config_data_seal(priv->l3cd_4);
+
if (nm_modem_get_state(NM_MODEM(self)) != NM_MODEM_STATE_CONNECTED) {
_LOGI("emitting PREPARE_RESULT: %s", ret ? "TRUE" : "FALSE");
nm_modem_emit_prepare_result(NM_MODEM(self),
@@ -917,20 +919,19 @@ static_stage3_ip4_config_start(NMModem * modem,
NMActRequest * req,
NMDeviceStateReason *out_failure_reason)
{
- NMModemOfono * self = NM_MODEM_OFONO(modem);
- NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
- GError * error = NULL;
+ NMModemOfono * self = NM_MODEM_OFONO(modem);
+ NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
- if (!priv->ip4_config) {
+ if (!priv->l3cd_4) {
_LOGD("IP4 config not ready(?)");
return NM_ACT_STAGE_RETURN_FAILURE;
}
_LOGD("IP4 config is done; setting modem_state -> CONNECTED");
- g_signal_emit_by_name(self, NM_MODEM_IP4_CONFIG_RESULT, priv->ip4_config, error);
- /* Signal listener takes ownership of the IP4Config */
- priv->ip4_config = NULL;
+ nm_modem_emit_signal_new_config(NM_MODEM(self), AF_INET, priv->l3cd_4, FALSE, NULL, NULL);
+
+ nm_clear_l3cd(&priv->l3cd_4);
nm_modem_set_state(NM_MODEM(self),
NM_MODEM_STATE_CONNECTED,
@@ -1040,7 +1041,7 @@ context_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data)
* clear it so that we can gate getting the IP config from oFono
* on whether or not we have already received them
*/
- g_clear_object(&priv->ip4_config);
+ nm_clear_l3cd(&priv->l3cd_4);
/* We need to directly query ConnectionContextinteface to get the current
* property values */
@@ -1258,7 +1259,7 @@ dispose(GObject *object)
priv->connect_properties = NULL;
}
- g_clear_object(&priv->ip4_config);
+ nm_clear_l3cd(&priv->l3cd_4);
if (priv->modem_proxy) {
g_signal_handlers_disconnect_by_data(priv->modem_proxy, self);
diff --git a/src/core/devices/wwan/nm-modem.c b/src/core/devices/wwan/nm-modem.c
index fee101a91a..405077c52f 100644
--- a/src/core/devices/wwan/nm-modem.c
+++ b/src/core/devices/wwan/nm-modem.c
@@ -20,8 +20,7 @@
#include "devices/nm-device-private.h"
#include "nm-netns.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "nm-l3-config-data.h"
#include "ppp/nm-ppp-manager-call.h"
#include "ppp/nm-ppp-status.h"
@@ -45,8 +44,7 @@ enum {
PPP_STATS,
PPP_FAILED,
PREPARE_RESULT,
- IP4_CONFIG_RESULT,
- IP6_CONFIG_RESULT,
+ NEW_CONFIG,
AUTH_REQUESTED,
AUTH_RESULT,
REMOVED,
@@ -67,18 +65,17 @@ typedef struct _NMModemPrivate {
* We should rework the code that it's not necessary */
char *ip_iface;
- int ip_ifindex;
- NMModemIPMethod ip4_method;
- NMModemIPMethod ip6_method;
- NMUtilsIPv6IfaceId iid;
- NMModemState state;
- NMModemState prev_state; /* revert to this state if enable/disable fails */
- char * device_id;
- char * sim_id;
- NMModemIPType ip_types;
- char * sim_operator_id;
- char * operator_code;
- char * apn;
+ int ip_ifindex;
+ NMModemIPMethod ip4_method;
+ NMModemIPMethod ip6_method;
+ NMModemState state;
+ NMModemState prev_state; /* revert to this state if enable/disable fails */
+ char * device_id;
+ char * sim_id;
+ NMModemIPType ip_types;
+ char * sim_operator_id;
+ char * operator_code;
+ char * apn;
NMPPPManager *ppp_manager;
@@ -88,11 +85,6 @@ typedef struct _NMModemPrivate {
guint mm_ip_timeout;
- guint32 ip4_route_table;
- guint32 ip4_route_metric;
- guint32 ip6_route_table;
- guint32 ip6_route_metric;
-
/* PPP stats */
guint32 in_bytes;
guint32 out_bytes;
@@ -180,6 +172,41 @@ nm_modem_state_to_string(NMModemState state)
/*****************************************************************************/
+void
+nm_modem_emit_signal_new_config(NMModem * self,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ gboolean do_slaac,
+ const NMUtilsIPv6IfaceId *iid,
+ GError * error)
+{
+ nm_assert(NM_IS_MODEM(self));
+ nm_assert_addr_family(addr_family);
+ nm_assert(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd));
+ nm_assert(!do_slaac || addr_family == AF_INET6);
+ nm_assert(!iid || addr_family == AF_INET6);
+ nm_assert(!error || (!l3cd && !do_slaac && !iid));
+
+ if (error) {
+ do_slaac = FALSE;
+ l3cd = NULL;
+ iid = NULL;
+ goto out_emit;
+ }
+
+ if (addr_family == AF_INET6) {
+ do_slaac = !!do_slaac;
+ } else {
+ iid = NULL;
+ do_slaac = FALSE;
+ }
+ if (l3cd)
+ nm_l3_config_data_seal(l3cd);
+
+out_emit:
+ g_signal_emit(self, signals[NEW_CONFIG], 0, addr_family, l3cd, do_slaac, iid, error);
+}
+
gboolean
nm_modem_is_claimed(NMModem *self)
{
@@ -523,66 +550,73 @@ ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpoin
}
static void
-ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
+ppp_new_config(NMPPPManager * ppp_manager,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid,
+ gpointer user_data)
{
- NMModem *self = NM_MODEM(user_data);
- guint32 i, num;
- guint32 bad_dns1 = htonl(0x0A0B0C0D);
- guint32 good_dns1 = htonl(0x04020201); /* GTE nameserver */
- guint32 bad_dns2 = htonl(0x0A0B0C0E);
- guint32 good_dns2 = htonl(0x04020202); /* GTE nameserver */
- gboolean dns_workaround = FALSE;
-
- /* Work around a PPP bug (#1732) which causes many mobile broadband
- * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers.
- * Apparently fixed in ppp-2.4.5 but we've had some reports that this is
- * not the case.
- *
- * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=2e09ef6886bbf00bc5a9a641110f801e372ffde6
- * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=f8191bf07df374f119a07910a79217c7618f113e
- */
-
- num = nm_ip4_config_get_num_nameservers(config);
- if (num == 2) {
- gboolean found1 = FALSE, found2 = FALSE;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd_modified = NULL;
+ NMModem * self = NM_MODEM(user_data);
+ gboolean do_slaac = FALSE;
- for (i = 0; i < num; i++) {
- guint32 ns = nm_ip4_config_get_nameserver(config, i);
+ nm_assert_addr_family(addr_family);
- if (ns == bad_dns1)
- found1 = TRUE;
- else if (ns == bad_dns2)
- found2 = TRUE;
+ if (addr_family == AF_INET6) {
+ if (!l3cd)
+ do_slaac = TRUE;
+ else {
+ do_slaac = !!nm_l3_config_data_get_first_obj(l3cd,
+ NMP_OBJECT_TYPE_IP6_ADDRESS,
+ nmp_object_ip6_address_is_not_link_local);
+ }
+ } else {
+ nm_assert(!iid);
+ iid = NULL;
+
+ if (l3cd) {
+ const in_addr_t bad_dns1 = htonl(0x0A0B0C0D);
+ const in_addr_t good_dns1 = htonl(0x04020201); /* GTE nameserver */
+ const in_addr_t bad_dns2 = htonl(0x0A0B0C0E);
+ const in_addr_t good_dns2 = htonl(0x04020202); /* GTE nameserver */
+ gboolean dns_workaround = FALSE;
+ const in_addr_t *addrs;
+ guint num;
+
+ /* Work around a PPP bug (#1732) which causes many mobile broadband
+ * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers.
+ * Apparently fixed in ppp-2.4.5 but we've had some reports that this is
+ * not the case.
+ *
+ * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=2e09ef6886bbf00bc5a9a641110f801e372ffde6
+ * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=f8191bf07df374f119a07910a79217c7618f113e
+ */
+
+ addrs = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &num);
+ if (num == 0)
+ dns_workaround = TRUE;
+ else if (num == 2) {
+ /* Be somewhat conservative about substitutions; the "bad" nameservers
+ * could actually be valid in some cases, so only substitute if ppp
+ * returns *only* the two bad nameservers.
+ */
+ dns_workaround = (addrs[0] == bad_dns1 && addrs[1] == bad_dns2)
+ || (addrs[1] == bad_dns1 && addrs[0] == bad_dns2);
+ } else
+ dns_workaround = FALSE;
+
+ if (dns_workaround) {
+ _LOGW("compensating for invalid PPP-provided nameservers");
+ l3cd_modified = nm_l3_config_data_new_clone(l3cd, 0);
+ nm_l3_config_data_clear_nameservers(l3cd_modified, AF_INET);
+ nm_l3_config_data_add_nameserver(l3cd_modified, AF_INET, &good_dns1);
+ nm_l3_config_data_add_nameserver(l3cd_modified, AF_INET, &good_dns2);
+ l3cd = nm_l3_config_data_seal(l3cd_modified);
+ }
}
-
- /* Be somewhat conservative about substitutions; the "bad" nameservers
- * could actually be valid in some cases, so only substitute if ppp
- * returns *only* the two bad nameservers.
- */
- dns_workaround = (found1 && found2);
- }
-
- if (!num || dns_workaround) {
- _LOGW("compensating for invalid PPP-provided nameservers");
- nm_ip4_config_reset_nameservers(config);
- nm_ip4_config_add_nameserver(config, good_dns1);
- nm_ip4_config_add_nameserver(config, good_dns2);
}
- g_signal_emit(self, signals[IP4_CONFIG_RESULT], 0, config, NULL);
-}
-
-static void
-ppp_ip6_config(NMPPPManager * ppp_manager,
- const NMUtilsIPv6IfaceId *iid,
- NMIP6Config * config,
- gpointer user_data)
-{
- NMModem *self = NM_MODEM(user_data);
-
- NM_MODEM_GET_PRIVATE(self)->iid = *iid;
-
- nm_modem_emit_ip6_config_result(self, config, NULL);
+ nm_modem_emit_signal_new_config(self, addr_family, l3cd, do_slaac, iid, NULL);
}
static void
@@ -679,14 +713,6 @@ ppp_stage3_ip_config_start(NMModem * self,
priv->ppp_manager = nm_ppp_manager_create(priv->data_port, &error);
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- priv->ip4_route_table,
- priv->ip4_route_metric,
- priv->ip6_route_table,
- priv->ip6_route_metric);
- }
-
if (!priv->ppp_manager
|| !nm_ppp_manager_start(priv->ppp_manager,
req,
@@ -710,12 +736,8 @@ ppp_stage3_ip_config_start(NMModem * self,
G_CALLBACK(ppp_ifindex_set),
self);
g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_CALLBACK(ppp_ip4_config),
- self);
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP6_CONFIG,
- G_CALLBACK(ppp_ip6_config),
+ NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
+ G_CALLBACK(ppp_new_config),
self);
g_signal_connect(priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATS, G_CALLBACK(ppp_stats), self);
@@ -748,8 +770,6 @@ nm_modem_stage3_ip4_config_start(NMModem * self,
connection = nm_act_request_get_applied_connection(req);
g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
- nm_modem_set_route_parameters_from_device(self, device);
-
method = nm_utils_get_ip_config_method(connection, AF_INET);
/* Only Disabled and Auto methods make sense for WWAN */
@@ -787,9 +807,11 @@ nm_modem_stage3_ip4_config_start(NMModem * self,
}
void
-nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config)
+nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device)
{
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(modem);
+ //XXX
+#if 0
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (modem);
/* If the modem has an ethernet-type data interface (ie, not PPP and thus
* not point-to-point) and IP config has a /32 prefix, then we assume that
@@ -806,40 +828,11 @@ nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config)
IFF_NOARP,
TRUE);
}
+#endif
}
/*****************************************************************************/
-void
-nm_modem_emit_ip6_config_result(NMModem *self, NMIP6Config *config, GError *error)
-{
- NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self);
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *addr;
- gboolean do_slaac = TRUE;
-
- if (error) {
- g_signal_emit(self, signals[IP6_CONFIG_RESULT], 0, NULL, FALSE, error);
- return;
- }
-
- if (config) {
- /* If the IPv6 configuration only included a Link-Local address, then
- * we have to run SLAAC to get the full IPv6 configuration.
- */
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, config, &addr) {
- if (IN6_IS_ADDR_LINKLOCAL(&addr->address)) {
- if (!priv->iid.id)
- priv->iid.id = ((guint64 *) (&addr->address.s6_addr))[1];
- } else
- do_slaac = FALSE;
- }
- }
- g_assert(config || do_slaac);
-
- g_signal_emit(self, signals[IP6_CONFIG_RESULT], 0, config, do_slaac, NULL);
-}
-
static NMActStageReturn
stage3_ip6_config_request(NMModem *self, NMDeviceStateReason *out_failure_reason)
{
@@ -866,8 +859,6 @@ nm_modem_stage3_ip6_config_start(NMModem * self,
connection = nm_act_request_get_applied_connection(req);
g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
- nm_modem_set_route_parameters_from_device(self, device);
-
method = nm_utils_get_ip_config_method(connection, AF_INET6);
/* Only Ignore, Disabled and Auto methods make sense for WWAN */
@@ -1540,82 +1531,6 @@ nm_modem_owns_port(NMModem *self, const char *iface)
return NM_IN_STRSET(iface, priv->ip_iface, priv->data_port, priv->control_port);
}
-gboolean
-nm_modem_get_iid(NMModem *self, NMUtilsIPv6IfaceId *out_iid)
-{
- g_return_val_if_fail(NM_IS_MODEM(self), FALSE);
-
- *out_iid = NM_MODEM_GET_PRIVATE(self)->iid;
- return TRUE;
-}
-
-/*****************************************************************************/
-
-void
-nm_modem_get_route_parameters(NMModem *self,
- guint32 *out_ip4_route_table,
- guint32 *out_ip4_route_metric,
- guint32 *out_ip6_route_table,
- guint32 *out_ip6_route_metric)
-{
- NMModemPrivate *priv;
-
- g_return_if_fail(NM_IS_MODEM(self));
-
- priv = NM_MODEM_GET_PRIVATE(self);
- NM_SET_OUT(out_ip4_route_table, priv->ip4_route_table);
- NM_SET_OUT(out_ip4_route_metric, priv->ip4_route_metric);
- NM_SET_OUT(out_ip6_route_table, priv->ip6_route_table);
- NM_SET_OUT(out_ip6_route_metric, priv->ip6_route_metric);
-}
-
-void
-nm_modem_set_route_parameters(NMModem *self,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric)
-{
- NMModemPrivate *priv;
-
- g_return_if_fail(NM_IS_MODEM(self));
-
- priv = NM_MODEM_GET_PRIVATE(self);
- if (priv->ip4_route_table != ip4_route_table || priv->ip4_route_metric != ip4_route_metric
- || priv->ip6_route_table != ip6_route_table || priv->ip6_route_metric != ip6_route_metric) {
- priv->ip4_route_table = ip4_route_table;
- priv->ip4_route_metric = ip4_route_metric;
- priv->ip6_route_table = ip6_route_table;
- priv->ip6_route_metric = ip6_route_metric;
-
- _LOGT("route-parameters: table-v4: %u, metric-v4: %u, table-v6: %u, metric-v6: %u",
- priv->ip4_route_table,
- priv->ip4_route_metric,
- priv->ip6_route_table,
- priv->ip6_route_metric);
- }
-
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- priv->ip4_route_table,
- priv->ip4_route_metric,
- priv->ip6_route_table,
- priv->ip6_route_metric);
- }
-}
-
-void
-nm_modem_set_route_parameters_from_device(NMModem *self, NMDevice *device)
-{
- g_return_if_fail(NM_IS_DEVICE(device));
-
- nm_modem_set_route_parameters(self,
- nm_device_get_route_table(device, AF_INET),
- nm_device_get_route_metric(device, AF_INET),
- nm_device_get_route_table(device, AF_INET6),
- nm_device_get_route_metric(device, AF_INET6));
-}
-
/*****************************************************************************/
void
@@ -1768,11 +1683,7 @@ nm_modem_init(NMModem *self)
self->_priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_MODEM, NMModemPrivate);
priv = self->_priv;
- priv->ip_ifindex = -1;
- priv->ip4_route_table = RT_TABLE_MAIN;
- priv->ip4_route_metric = 700;
- priv->ip6_route_table = RT_TABLE_MAIN;
- priv->ip6_route_metric = 700;
+ priv->ip_ifindex = -1;
}
static void
@@ -1946,43 +1857,27 @@ nm_modem_class_init(NMModemClass *klass)
1,
G_TYPE_UINT);
- signals[IP4_CONFIG_RESULT] = g_signal_new(NM_MODEM_IP4_CONFIG_RESULT,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 2,
- G_TYPE_OBJECT,
- G_TYPE_POINTER);
-
- /**
- * NMModem::ip6-config-result:
- * @modem: the #NMModem on which the signal is emitted
- * @config: the #NMIP6Config to apply to the modem's data port
- * @do_slaac: %TRUE if IPv6 SLAAC should be started
- * @error: a #GError if any error occurred during IP configuration
- *
- * This signal is emitted when IPv6 configuration has completed or failed.
- * If @error is set the configuration failed. If @config is set, then
+ /*
+ * This signal is emitted when IP configuration has completed or failed.
+ * If @error is set the configuration failed. If @l3cd is set, then
* the details should be applied to the data port before any further
- * configuration (like SLAAC) is done. @do_slaac indicates whether SLAAC
- * should be started after applying @config to the data port.
+ * configuration (like SLAAC) is done. @do_slaac indicates whether SLAAC
+ * should be started after applying @l3cd to the data port.
*/
- signals[IP6_CONFIG_RESULT] = g_signal_new(NM_MODEM_IP6_CONFIG_RESULT,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 3,
- G_TYPE_OBJECT,
- G_TYPE_BOOLEAN,
- G_TYPE_POINTER);
+ signals[NEW_CONFIG] = g_signal_new(NM_MODEM_NEW_CONFIG,
+ G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_INT, /* int addr_family */
+ G_TYPE_POINTER, /* const NML3ConfigData *l3cd */
+ G_TYPE_BOOLEAN, /* gboolean do_slaac */
+ G_TYPE_POINTER, /* const NMUtilsIPv6IfaceId *iid */
+ G_TYPE_POINTER); /* GError *error */
signals[PREPARE_RESULT] = g_signal_new(NM_MODEM_PREPARE_RESULT,
G_OBJECT_CLASS_TYPE(object_class),
diff --git a/src/core/devices/wwan/nm-modem.h b/src/core/devices/wwan/nm-modem.h
index 4bc81ff8dd..bc890279f1 100644
--- a/src/core/devices/wwan/nm-modem.h
+++ b/src/core/devices/wwan/nm-modem.h
@@ -32,15 +32,14 @@
#define NM_MODEM_APN "apn"
/* Signals */
-#define NM_MODEM_PPP_STATS "ppp-stats"
-#define NM_MODEM_PPP_FAILED "ppp-failed"
-#define NM_MODEM_PREPARE_RESULT "prepare-result"
-#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result"
-#define NM_MODEM_IP6_CONFIG_RESULT "ip6-config-result"
-#define NM_MODEM_AUTH_REQUESTED "auth-requested"
-#define NM_MODEM_AUTH_RESULT "auth-result"
-#define NM_MODEM_REMOVED "removed"
-#define NM_MODEM_STATE_CHANGED "state-changed"
+#define NM_MODEM_PPP_STATS "ppp-stats"
+#define NM_MODEM_PPP_FAILED "ppp-failed"
+#define NM_MODEM_PREPARE_RESULT "prepare-result"
+#define NM_MODEM_NEW_CONFIG "new-config"
+#define NM_MODEM_AUTH_REQUESTED "auth-requested"
+#define NM_MODEM_AUTH_RESULT "auth-result"
+#define NM_MODEM_REMOVED "removed"
+#define NM_MODEM_STATE_CHANGED "state-changed"
typedef enum {
NM_MODEM_IP_METHOD_UNKNOWN = 0,
@@ -161,7 +160,6 @@ const char *nm_modem_get_driver(NMModem *modem);
const char *nm_modem_get_device_id(NMModem *modem);
const char *nm_modem_get_sim_id(NMModem *modem);
const char *nm_modem_get_sim_operator_id(NMModem *modem);
-gboolean nm_modem_get_iid(NMModem *modem, NMUtilsIPv6IfaceId *out_iid);
const char *nm_modem_get_operator_code(NMModem *modem);
const char *nm_modem_get_apn(NMModem *modem);
@@ -188,20 +186,6 @@ gboolean nm_modem_complete_connection(NMModem * self,
NMConnection *const *existing_connections,
GError ** error);
-void nm_modem_get_route_parameters(NMModem *self,
- guint32 *out_ip4_route_table,
- guint32 *out_ip4_route_metric,
- guint32 *out_ip6_route_table,
- guint32 *out_ip6_route_metric);
-
-void nm_modem_set_route_parameters(NMModem *self,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric);
-
-void nm_modem_set_route_parameters_from_device(NMModem *modem, NMDevice *device);
-
NMActStageReturn nm_modem_act_stage1_prepare(NMModem * modem,
NMActRequest * req,
NMDeviceStateReason *out_failure_reason);
@@ -217,7 +201,7 @@ NMActStageReturn nm_modem_stage3_ip6_config_start(NMModem * modem,
NMDevice * device,
NMDeviceStateReason *out_failure_reason);
-void nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config);
+void nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device);
void nm_modem_get_secrets(NMModem * modem,
const char *setting_name,
@@ -256,7 +240,13 @@ void nm_modem_emit_ppp_failed(NMModem *self, NMDeviceStateReason reason);
GArray *nm_modem_get_connection_ip_type(NMModem *self, NMConnection *connection, GError **error);
/* For subclasses */
-void nm_modem_emit_ip6_config_result(NMModem *self, NMIP6Config *config, GError *error);
+
+void nm_modem_emit_signal_new_config(NMModem * self,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ gboolean do_slaac,
+ const NMUtilsIPv6IfaceId *iid,
+ GError * error);
const char *nm_modem_ip_type_to_string(NMModemIPType ip_type);
diff --git a/src/core/dhcp/README.next.md b/src/core/dhcp/README.next.md
new file mode 100644
index 0000000000..88fa6683c7
--- /dev/null
+++ b/src/core/dhcp/README.next.md
@@ -0,0 +1,103 @@
+`NMDhcpClient`
+==============
+
+Using `NMDhcpClient` still requires a lot of logic in `NMDevice`. The main goal
+is to simplify `NMDevice`, so `NMDhcpClient` must become more complicated to
+provide a simpler (but robust) API.
+
+NMDevice has basically two timeouts (talking about IPv4, but it applies
+similarly to IPv6): `ipv4.dhcp-timeout` and `ipv4.required-timeout`. They
+control how long NMDevice is willing to try, before failing the activation
+altogether. Note that with `ipv4.may-fail=yes`, we may very well never want to
+fail the activation entirely, regardless how DHCP is doing. In that case we
+want to stay up, but also constantly retrying whether we cannot get a lease and
+recover.
+
+Currently, if `NMDhcpClient` signals a failure, then it's basically up to
+`NMDevice` to schedule and retry. That is complicated, and we should move the
+complexity out of `NMDevice`.
+
+`NMDhcpClient` should have a simpler API:
+
+- `nm_dhcp_manager_start_ip[46]()`: creates (and starts) a `NMDhcpClient`
+ instance. The difference is, this function tries really hard not to fail
+ to create an `NMDhcpClient`. There is no explicit `start()`, but note that the
+ instance must not emit any signals before the next maincontext iteration. That is,
+ it only will call back the user after a timeout/idle or some other IO event, which
+ happens during a future iteration of the maincontext.
+
+- `nm_dhcp_client_stop()`: when `NMDevice` is done with the `NMDhcpClient`
+ instance, it will stop it and throw it away. This method exists because
+ `NMDhcpClient` is a `GObject` and ref-counted. Thus, we don't want to rely on
+ the last unref to stop the instance, but have an explicit stop. After stop, the
+ instance is defunct and won't emit any signals anymore. The class does not need
+ to support restarting a stopped instance. If `NMDevice` wants to restart DHCP, it
+ should create a new one. `NMDevice` would only want to do that, if the parameters
+ change, hence a new instance is in order (and no need for the complexity of
+ restart in `NMDhcpClient`).
+
+- as already now, `NMDhcpClient` is not very configurable. You provide most
+ (all) parameters during `nm_dhcp_manager_start_ip[46]()`, and then it keeps
+ running until stop.
+
+- `NMDhcpClient` exposes a simple state to the user:
+
+ 1. "no lease, but good". When starting, there is no lease, but we are
+ optimistic to get one. This is the inital state, but we can also get back to
+ this state after we had a lease (which might expire).
+
+ 1. "has a lease". Here there is no need to distinguish whether the current
+ lease was the first we received, or whether this was an update. In this state,
+ the instance has a lease and we are good.
+
+ 1. "no lease, but bad". `NMDhcpClient` tries really hard, and "bad" does not
+ mean that it gave up. It will keep retrying, it's just that there is little
+ hope of getting a new lease. This happens, when you try to run DHCP on a Layer3
+ link (WireGuard). There is little hope to succeed, but `NMDhcpClient`
+ (theoretically) will retry and may recover from this. Another example is when
+ we fail to start dhclient because it's not installed. In that case, we are not
+ optimistic to recover, however `NMDhcpDhclient` will retry (with backoff
+ timeout) and might still recover from this. For most cases, `NMDevice` will
+ treat the no-lease cases the same, but in case of "bad" it might give up
+ earlier.
+
+When a lease expires, that does not necessarily mean that we are now in a bad
+state. It might mean that the DHCP server is temporarily down, but we might
+recover from that easily. "bad" really means, something is wrong on our side
+which prevents us from getting a lease. Also, imagine `dhclient` dies (we would
+try to restart, but assume that fails too), but we still have a valid lease,
+then possibly `NMDhcpClient` should still pretend all is good and we still have
+a lease until it expires. It may be we can recover before that happens. The
+point of all of this, is to hide errors as much as possibly and automatically
+recover. `NMDevice` will decide to tear down, if we didn't get a lease after
+`ipv4.dhcp-timeout`. That's the main criteria, and it might not even
+distinguish between "no lease, but good" and "no lease, but bad".
+
+- `NMDhcpClient` will also take care of the `ipv4.dhcp-timeout` grace period.
+ That timeout is provided during start, and starts ticking whenever there is
+ no lease. When it expires, a timeout signal gets emitted. That's it. This is
+ independent from the 3 states above, and only saves `NMDevice` from scheduling
+ this timer themselves.
+ This is NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT notification.
+
+- for nettools, `nm_dhcp_client_can_accept()` indicates that when we receive a
+ lease, we need to accept/decline it first. In that case, `NMDevice`
+optionally does ACD first, then configures the IP address first and calls
+`nm_dhcp_client_accept()`. In case of ACD conflict, it will call
+`nm_dhcp_client_decline()` (which optimally causes `NMDhcpClient` to get a
+different lease). With this, the above state "has a lease" has actually three
+flavors: "has a lease but not yet ACD probed" and "has a lease but
+accepted/declined" (but `NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED` gets only emitted
+when we get the lease, not when we accept/decline it). With `dhclient`, when we
+receive a lease, it means "has a lease but accepted" right away.
+
+- for IPv6 prefix delegation, there is also `needed_prefixes` and
+ `NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED`. Currently `needed_prefixes` needs
+ to be specified during start (which simplifies things). Maybe `needed_prefixes`
+ should be changable at runtime. Otherwise, whether we have prefixes is similar
+ to whether we have a lease, and the simple 3 states apply.
+
+When NetworkManager quits, it may want to leave the interface up. In that case,
+we still always want to stop the DHCP client, but possibly not deconfiguring
+the interface. I don't think that this concerns `NMDhcpClient`, because `NMDhcpClient`
+only provides the lease information and `NMDevice` is responsible to configure it.
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index f88c79c0be..6f71a44501 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -20,9 +20,13 @@
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
+#include "nm-l3cfg.h"
+#include "nm-l3-config-data.h"
#include "nm-dhcp-utils.h"
#include "nm-dhcp-options.h"
#include "libnm-platform/nm-platform.h"
+#include "nm-hostname-manager.h"
+#include "libnm-systemd-shared/nm-sd-utils-shared.h"
#include "nm-dhcp-client-logging.h"
@@ -32,53 +36,19 @@ enum { SIGNAL_NOTIFY, LAST_SIGNAL };
static guint signals[LAST_SIGNAL] = {0};
-NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient,
- PROP_ADDR_FAMILY,
- PROP_ANYCAST_ADDRESS,
- PROP_FLAGS,
- PROP_HWADDR,
- PROP_BROADCAST_HWADDR,
- PROP_IFACE,
- PROP_IFINDEX,
- PROP_MULTI_IDX,
- PROP_ROUTE_METRIC,
- PROP_ROUTE_TABLE,
- PROP_TIMEOUT,
- PROP_UUID,
- PROP_IAID,
- PROP_IAID_EXPLICIT,
- PROP_HOSTNAME,
- PROP_HOSTNAME_FLAGS,
- PROP_MUD_URL,
- PROP_VENDOR_CLASS_IDENTIFIER,
- PROP_REJECT_SERVERS, );
+NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient, PROP_CONFIG, );
typedef struct _NMDhcpClientPrivate {
- NMDedupMultiIndex * multi_idx;
- char * iface;
- GBytes * hwaddr;
- GBytes * bcast_hwaddr;
- char * uuid;
- GBytes * client_id;
- char * hostname;
- const char ** reject_servers;
- char * mud_url;
- char * anycast_address;
- GBytes * vendor_class_identifier;
- pid_t pid;
- guint timeout_id;
- guint watch_id;
- int addr_family;
- int ifindex;
- guint32 route_table;
- guint32 route_metric;
- guint32 timeout;
- guint32 iaid;
- NMDhcpState state;
- NMDhcpHostnameFlags hostname_flags;
- NMDhcpClientFlags client_flags;
- bool iaid_explicit : 1;
- bool is_stopped : 1;
+ NMDhcpClientConfig config;
+ const NML3ConfigData *l3cd;
+ GSource * no_lease_timeout_source;
+ pid_t pid;
+ guint timeout_id;
+ guint watch_id;
+ NMDhcpState state;
+ bool iaid_explicit : 1;
+ bool is_stopped : 1;
+ GBytes * effective_client_id;
} NMDhcpClientPrivate;
G_DEFINE_ABSTRACT_TYPE(NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT)
@@ -98,25 +68,6 @@ _emit_notify(NMDhcpClient *self, const NMDhcpClientNotifyData *notify_data)
g_signal_emit(G_OBJECT(self), signals[SIGNAL_NOTIFY], 0, notify_data);
}
-static void
-_emit_notify_state_changed(NMDhcpClient *self,
- NMDhcpState dhcp_state,
- NMIPConfig * ip_config,
- GHashTable * options)
-{
- const NMDhcpClientNotifyData notify_data = {
- .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED,
- .state_changed =
- {
- .dhcp_state = dhcp_state,
- .ip_config = ip_config,
- .options = options,
- },
- };
-
- _emit_notify(self, &notify_data);
-}
-
/*****************************************************************************/
pid_t
@@ -127,149 +78,24 @@ nm_dhcp_client_get_pid(NMDhcpClient *self)
return NM_DHCP_CLIENT_GET_PRIVATE(self)->pid;
}
-NMDedupMultiIndex *
-nm_dhcp_client_get_multi_idx(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->multi_idx;
-}
-
-const char *
-nm_dhcp_client_get_iface(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->iface;
-}
-
-int
-nm_dhcp_client_get_ifindex(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), -1);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->ifindex;
-}
-
-int
-nm_dhcp_client_get_addr_family(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), AF_UNSPEC);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->addr_family;
-}
-
-const char *
-nm_dhcp_client_get_uuid(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->uuid;
-}
-
-GBytes *
-nm_dhcp_client_get_hw_addr(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->hwaddr;
-}
-
-GBytes *
-nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->bcast_hwaddr;
-}
-
-guint32
-nm_dhcp_client_get_route_table(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), RT_TABLE_MAIN);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->route_table;
-}
-
-void
-nm_dhcp_client_set_route_table(NMDhcpClient *self, guint32 route_table)
-{
- NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
-
- if (route_table != priv->route_table) {
- priv->route_table = route_table;
- _notify(self, PROP_ROUTE_TABLE);
- }
-}
-
-guint32
-nm_dhcp_client_get_route_metric(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), G_MAXUINT32);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->route_metric;
-}
-
-void
-nm_dhcp_client_set_route_metric(NMDhcpClient *self, guint32 route_metric)
-{
- NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
-
- if (route_metric != priv->route_metric) {
- priv->route_metric = route_metric;
- _notify(self, PROP_ROUTE_METRIC);
- }
-}
-
-guint32
-nm_dhcp_client_get_timeout(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), 0);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->timeout;
-}
-
-guint32
-nm_dhcp_client_get_iaid(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), 0);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->iaid;
-}
-
-gboolean
-nm_dhcp_client_get_iaid_explicit(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->iaid_explicit;
-}
-
-GBytes *
-nm_dhcp_client_get_client_id(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->client_id;
-}
-
static void
-_set_client_id(NMDhcpClient *self, GBytes *client_id, gboolean take)
+_set_effective_client_id(NMDhcpClient *self, GBytes *client_id, gboolean take)
{
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
nm_assert(!client_id || g_bytes_get_size(client_id) >= 2);
- if (priv->client_id == client_id
- || (priv->client_id && client_id && g_bytes_equal(priv->client_id, client_id))) {
+ if (priv->effective_client_id == client_id
+ || (priv->effective_client_id && client_id
+ && g_bytes_equal(priv->effective_client_id, client_id))) {
if (take && client_id)
g_bytes_unref(client_id);
return;
}
- if (priv->client_id)
- g_bytes_unref(priv->client_id);
- priv->client_id = client_id;
+ if (priv->effective_client_id)
+ g_bytes_unref(priv->effective_client_id);
+ priv->effective_client_id = client_id;
if (!take && client_id)
g_bytes_ref(client_id);
@@ -277,94 +103,20 @@ _set_client_id(NMDhcpClient *self, GBytes *client_id, gboolean take)
gs_free char *s = NULL;
_LOGT("%s: set %s",
- nm_dhcp_client_get_addr_family(self) == AF_INET6 ? "duid" : "client-id",
- priv->client_id ? (s = nm_dhcp_utils_duid_to_string(priv->client_id)) : "default");
+ priv->config.addr_family == AF_INET6 ? "duid" : "client-id",
+ priv->effective_client_id
+ ? (s = nm_dhcp_utils_duid_to_string(priv->effective_client_id))
+ : "default");
}
}
void
-nm_dhcp_client_set_client_id(NMDhcpClient *self, GBytes *client_id)
+nm_dhcp_client_set_effective_client_id(NMDhcpClient *self, GBytes *client_id)
{
g_return_if_fail(NM_IS_DHCP_CLIENT(self));
g_return_if_fail(!client_id || g_bytes_get_size(client_id) >= 2);
- _set_client_id(self, client_id, FALSE);
-}
-
-void
-nm_dhcp_client_set_client_id_bin(NMDhcpClient *self,
- guint8 type,
- const guint8 *client_id,
- gsize len)
-{
- guint8 *buf;
- GBytes *b;
-
- g_return_if_fail(NM_IS_DHCP_CLIENT(self));
- g_return_if_fail(client_id);
- g_return_if_fail(len > 0);
-
- buf = g_malloc(len + 1);
- buf[0] = type;
- memcpy(buf + 1, client_id, len);
- b = g_bytes_new_take(buf, len + 1);
- _set_client_id(self, b, TRUE);
-}
-
-const char *
-nm_dhcp_client_get_anycast_address(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->anycast_address;
-}
-
-const char *
-nm_dhcp_client_get_hostname(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->hostname;
-}
-
-NMDhcpHostnameFlags
-nm_dhcp_client_get_hostname_flags(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NM_DHCP_HOSTNAME_FLAG_NONE);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->hostname_flags;
-}
-
-NMDhcpClientFlags
-nm_dhcp_client_get_client_flags(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NM_DHCP_CLIENT_FLAGS_NONE);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->client_flags;
-}
-
-const char *
-nm_dhcp_client_get_mud_url(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->mud_url;
-}
-
-GBytes *
-nm_dhcp_client_get_vendor_class_identifier(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->vendor_class_identifier;
-}
-
-const char *const *
-nm_dhcp_client_get_reject_servers(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return (const char *const *) NM_DHCP_CLIENT_GET_PRIVATE(self)->reject_servers;
+ _set_effective_client_id(self, client_id, FALSE);
}
/*****************************************************************************/
@@ -457,78 +209,159 @@ stop(NMDhcpClient *self, gboolean release)
if (priv->pid > 0) {
/* Clean up the watch handler since we're explicitly killing the daemon */
watch_cleanup(self);
- nm_dhcp_client_stop_pid(priv->pid, priv->iface);
+ nm_dhcp_client_stop_pid(priv->pid, priv->config.iface);
}
priv->pid = -1;
}
-void
-nm_dhcp_client_set_state(NMDhcpClient *self,
- NMDhcpState new_state,
- NMIPConfig * ip_config,
- GHashTable * options)
+static gboolean
+_no_lease_timeout(gpointer user_data)
{
+ NMDhcpClient * self = user_data;
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+ nm_clear_g_source_inst(&priv->no_lease_timeout_source);
+
+ _emit_notify(self,
+ &((NMDhcpClientNotifyData){
+ .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT,
+ }));
+ return G_SOURCE_CONTINUE;
+}
+
+const NMDhcpClientConfig *
+nm_dhcp_client_get_config(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return &priv->config;
+}
+
+void
+nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, const NML3ConfigData *l3cd)
+{
+ NMDhcpClientPrivate * priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+ GHashTable * options;
+ const int IS_IPv4 = NM_IS_IPv4(priv->config.addr_family);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_merged = NULL;
+
+ g_return_if_fail(NM_IS_DHCP_CLIENT(self));
+
if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
- g_return_if_fail(NM_IS_IP_CONFIG_ADDR_FAMILY(ip_config, priv->addr_family));
- g_return_if_fail(options);
- } else {
- g_return_if_fail(!ip_config);
- g_return_if_fail(!options);
- }
+ g_return_if_fail(NM_IS_L3_CONFIG_DATA(l3cd));
+ g_return_if_fail(nm_l3_config_data_get_dhcp_lease(l3cd, priv->config.addr_family));
+ } else
+ g_return_if_fail(!l3cd);
+
+ if (l3cd)
+ nm_l3_config_data_seal(l3cd);
if (new_state >= NM_DHCP_STATE_BOUND)
timeout_cleanup(self);
if (new_state >= NM_DHCP_STATE_TIMEOUT)
watch_cleanup(self);
- /* The client may send same-state transitions for RENEW/REBIND events and
- * the lease may have changed, so handle same-state transitions for the
- * EXTENDED and BOUND states. Ignore same-state transitions for other
- * events since the lease won't have changed and the state was already handled.
- */
- if ((priv->state == new_state)
- && !NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED))
- return;
+ if (!IS_IPv4 && l3cd) {
+ if (nm_dhcp_utils_merge_new_dhcp6_lease(priv->l3cd, l3cd, &l3cd_merged)) {
+ l3cd = nm_l3_config_data_seal(l3cd_merged);
+ }
+ }
- if (_LOGD_ENABLED()) {
- gs_free const char **keys = NULL;
- guint i, nkeys;
+ if (priv->l3cd == l3cd)
+ return;
- keys = nm_strdict_get_keys(options, TRUE, &nkeys);
- for (i = 0; i < nkeys; i++) {
- _LOGD("option %-20s => '%s'", keys[i], (char *) g_hash_table_lookup(options, keys[i]));
+ if (l3cd)
+ nm_clear_g_source_inst(&priv->no_lease_timeout_source);
+ else {
+ /* FIXME(l3cfg:dhcp): we also need to start no_lease_timeout initially, if the
+ * instance starts without a previous_lease. */
+ if (!priv->no_lease_timeout_source && priv->l3cd) {
+ if (priv->config.timeout == NM_DHCP_TIMEOUT_INFINITY)
+ priv->no_lease_timeout_source = g_source_ref(nm_g_source_sentinel_get(0));
+ else {
+ priv->no_lease_timeout_source =
+ nm_g_timeout_add_source_seconds(priv->config.timeout, _no_lease_timeout, self);
+ }
}
}
- if (_LOGT_ENABLED() && priv->addr_family == AF_INET6) {
- gs_free char *event_id = NULL;
+ /* FIXME(l3cfg:dhcp): the API of NMDhcpClient is changing to expose a simpler API.
+ * The internals like NMDhcpState should not be exposed (or possibly dropped in large
+ * parts). */
+
+ nm_l3_config_data_reset(&priv->l3cd, l3cd);
+
+ options = l3cd ? nm_dhcp_lease_get_options(
+ nm_l3_config_data_get_dhcp_lease(l3cd, priv->config.addr_family))
+ : NULL;
+
+ if (_LOGD_ENABLED()) {
+ if (options) {
+ gs_free const char **keys = NULL;
+ guint nkeys;
+ guint i;
+
+ keys = nm_strdict_get_keys(options, TRUE, &nkeys);
+ for (i = 0; i < nkeys; i++) {
+ _LOGD("option %-20s => '%s'",
+ keys[i],
+ (char *) g_hash_table_lookup(options, keys[i]));
+ }
+
+ if (priv->config.addr_family == AF_INET6) {
+ gs_free char *event_id = NULL;
- event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
- if (event_id)
- _LOGT("event-id: \"%s\"", event_id);
+ event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
+ if (event_id)
+ _LOGT("event-id: \"%s\"", event_id);
+ }
+ }
}
if (_LOGI_ENABLED()) {
const char *req_str =
- NM_IS_IPv4(priv->addr_family)
- ? nm_dhcp_option_request_string(AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS)
- : nm_dhcp_option_request_string(AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS);
+ IS_IPv4 ? nm_dhcp_option_request_string(AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS)
+ : nm_dhcp_option_request_string(AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS);
const char *addr = nm_g_hash_table_lookup(options, req_str);
- _LOGI("state changed %s -> %s%s%s%s",
- nm_dhcp_state_to_string(priv->state),
- nm_dhcp_state_to_string(new_state),
+ _LOGI("state changed %s%s%s%s",
+ priv->l3cd ? "new lease" : "no lease",
NM_PRINT_FMT_QUOTED(addr, ", address=", addr, "", ""));
}
- priv->state = new_state;
+ /* FIXME(l3cfg:dhcp:acd): NMDhcpClient must also do ACD. It needs acd_timeout_msec
+ * as a configuration parameter (in NMDhcpClientConfig). When ACD is enabled,
+ * when a new lease gets announced, it must first use NML3Cfg to run ACD on the
+ * interface (the previous lease -- if any -- will still be used at that point).
+ * If ACD fails, we call nm_dhcp_client_decline() and try to get a different
+ * lease.
+ * If ACD passes, we need to notify the new lease, and the user (NMDevice) may
+ * then configure the address. We need to watch the configured addresses (in NML3Cfg),
+ * and if the address appears there, we need to accept the lease. That is complicated
+ * but necessary, because we can only accept the lease after we configured the
+ * address.
+ *
+ * As a whole, ACD is transparent for the user (NMDevice). It's entirely managed
+ * by NMDhcpClient. Note that we do ACD through NML3Cfg, which centralizes IP handling
+ * for one interface, so for example if the same address happens to be configured
+ * as a static address (bypassing ACD), then NML3Cfg is aware of that and signals
+ * immediate success. */
- _emit_notify_state_changed(self, new_state, ip_config, options);
+ {
+ const NMDhcpClientNotifyData notify_data = {
+ .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE,
+ .lease_update =
+ {
+ .l3cd = priv->l3cd,
+ },
+ };
+
+ _emit_notify(self, &notify_data);
+ }
}
-static gboolean
+/* FIXME(l3cfg:dhcp) */
+_nm_unused static gboolean
transaction_timeout(gpointer user_data)
{
NMDhcpClient * self = NM_DHCP_CLIENT(user_data);
@@ -536,7 +369,7 @@ transaction_timeout(gpointer user_data)
priv->timeout_id = 0;
_LOGW("request timed out");
- nm_dhcp_client_set_state(self, NM_DHCP_STATE_TIMEOUT, NULL, NULL);
+ nm_dhcp_client_set_state(self, NM_DHCP_STATE_TIMEOUT, NULL);
return G_SOURCE_REMOVE;
}
@@ -554,7 +387,7 @@ daemon_watch_cb(GPid pid, int status, gpointer user_data)
priv->pid = -1;
- nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL, NULL);
+ nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL);
}
void
@@ -566,10 +399,10 @@ nm_dhcp_client_start_timeout(NMDhcpClient *self)
/* Set up a timeout on the transaction to kill it after the timeout */
- if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY)
- return;
-
- priv->timeout_id = g_timeout_add_seconds(priv->timeout, transaction_timeout, self);
+ /* FIXME(l3cfg:dhcp): no-lease-timeout is only for convenience for the user (NMDevice).
+ * Whatever the purpose of nm_dhcp_client_start_timeout() is, it is not the same timer. */
+ return;
+ //priv->timeout_id = g_timeout_add_seconds(priv->no_lease_timeout, transaction_timeout, self);
}
void
@@ -599,10 +432,7 @@ nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid)
}
gboolean
-nm_dhcp_client_start_ip4(NMDhcpClient *self,
- GBytes * client_id,
- const char * last_ip4_address,
- GError ** error)
+nm_dhcp_client_start_ip4(NMDhcpClient *self, GError **error)
{
NMDhcpClientPrivate *priv;
@@ -610,24 +440,37 @@ nm_dhcp_client_start_ip4(NMDhcpClient *self,
priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
g_return_val_if_fail(priv->pid == -1, FALSE);
- g_return_val_if_fail(priv->addr_family == AF_INET, FALSE);
- g_return_val_if_fail(priv->uuid != NULL, FALSE);
-
- if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY)
+ g_return_val_if_fail(priv->config.addr_family == AF_INET, FALSE);
+ g_return_val_if_fail(priv->config.uuid, FALSE);
+
+ /* FIXME(l3cfg:dhcp:ipv6ll): for IPv6, NMDhcpClient needs to wait that
+ * a IPv6 LL address appears. The user (NMDevice) will start the generation
+ * of a LL address, but NMDhcpClient is already running and is just waiting.
+ *
+ * All the while, NM_DHCP_CLIENT_NO_LEASE_TIMEOUT is ticking. If the LL address
+ * does not appear in (e.g. 5 seconds), a NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD signal
+ * can be emitted. */
+
+ if (priv->config.timeout == NM_DHCP_TIMEOUT_INFINITY)
_LOGI("activation: beginning transaction (no timeout)");
else
- _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
+ _LOGI("activation: beginning transaction (timeout in %u seconds)",
+ (guint) priv->config.timeout);
- nm_dhcp_client_set_client_id(self, client_id);
-
- return NM_DHCP_CLIENT_GET_CLASS(self)->ip4_start(self, last_ip4_address, error);
+ return NM_DHCP_CLIENT_GET_CLASS(self)->ip4_start(self, error);
}
gboolean
nm_dhcp_client_accept(NMDhcpClient *self, GError **error)
{
+ NMDhcpClientPrivate *priv;
+
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
+ priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ g_return_val_if_fail(priv->l3cd, FALSE);
+
if (NM_DHCP_CLIENT_GET_CLASS(self)->accept) {
return NM_DHCP_CLIENT_GET_CLASS(self)->accept(self, error);
}
@@ -652,8 +495,14 @@ nm_dhcp_client_can_accept(NMDhcpClient *self)
gboolean
nm_dhcp_client_decline(NMDhcpClient *self, const char *error_message, GError **error)
{
+ NMDhcpClientPrivate *priv;
+
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
+ priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ g_return_val_if_fail(priv->l3cd, FALSE);
+
if (NM_DHCP_CLIENT_GET_CLASS(self)->decline) {
return NM_DHCP_CLIENT_GET_CLASS(self)->decline(self, error_message, error);
}
@@ -668,42 +517,31 @@ get_duid(NMDhcpClient *self)
}
gboolean
-nm_dhcp_client_start_ip6(NMDhcpClient * self,
- GBytes * client_id,
- gboolean enforce_duid,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error)
+nm_dhcp_client_start_ip6(NMDhcpClient *self, GError **error)
{
NMDhcpClientPrivate *priv;
gs_unref_bytes GBytes *own_client_id = NULL;
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
- g_return_val_if_fail(client_id, FALSE);
-
priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
g_return_val_if_fail(priv->pid == -1, FALSE);
- g_return_val_if_fail(priv->addr_family == AF_INET6, FALSE);
- g_return_val_if_fail(priv->uuid != NULL, FALSE);
- g_return_val_if_fail(!priv->client_id, FALSE);
+ g_return_val_if_fail(priv->config.addr_family == AF_INET6, FALSE);
+ g_return_val_if_fail(priv->config.uuid, FALSE);
+ g_return_val_if_fail(!priv->effective_client_id, FALSE);
- if (!enforce_duid)
+ if (!priv->config.v6.enforce_duid)
own_client_id = NM_DHCP_CLIENT_GET_CLASS(self)->get_duid(self);
- _set_client_id(self, own_client_id ?: client_id, FALSE);
+ _set_effective_client_id(self, own_client_id ?: priv->config.client_id, FALSE);
- if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY)
+ if (priv->config.timeout == NM_DHCP_TIMEOUT_INFINITY)
_LOGI("activation: beginning transaction (no timeout)");
else
- _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
+ _LOGI("activation: beginning transaction (timeout in %u seconds)",
+ (guint) priv->config.timeout);
- return NM_DHCP_CLIENT_GET_CLASS(self)->ip6_start(self,
- ll_addr,
- privacy,
- needed_prefixes,
- error);
+ return NM_DHCP_CLIENT_GET_CLASS(self)->ip6_start(self, error);
}
void
@@ -789,7 +627,7 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release)
_LOGI("canceled DHCP transaction");
nm_assert(priv->pid == -1);
- nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL, NULL);
+ nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL);
}
/*****************************************************************************/
@@ -921,12 +759,10 @@ nm_dhcp_client_handle_event(gpointer unused,
const char * reason,
NMDhcpClient *self)
{
- NMDhcpClientPrivate *priv;
- guint32 old_state;
- guint32 new_state;
- gs_unref_hashtable GHashTable *str_options = NULL;
- gs_unref_object NMIPConfig *ip_config = NULL;
- NMPlatformIP6Address prefix = {
+ NMDhcpClientPrivate * priv;
+ guint32 new_state;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP6Address prefix = {
0,
};
@@ -938,25 +774,26 @@ nm_dhcp_client_handle_event(gpointer unused,
priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
- if (g_strcmp0(priv->iface, iface) != 0)
+ if (!nm_streq0(priv->config.iface, iface))
return FALSE;
if (priv->pid != pid)
return FALSE;
- old_state = priv->state;
- new_state = reason_to_state(self, priv->iface, reason);
+ new_state = reason_to_state(self, priv->config.iface, reason);
+ if (new_state == NM_DHCP_STATE_NOOP)
+ return TRUE;
+
_LOGD("DHCP state '%s' -> '%s' (reason: '%s')",
- nm_dhcp_state_to_string(old_state),
+ nm_dhcp_state_to_string(priv->state),
nm_dhcp_state_to_string(new_state),
reason);
-
- if (new_state == NM_DHCP_STATE_NOOP)
- return TRUE;
+ priv->state = new_state;
if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
- GVariantIter iter;
- const char * name;
- GVariant * value;
+ gs_unref_hashtable GHashTable *str_options = NULL;
+ GVariantIter iter;
+ const char * name;
+ GVariant * value;
/* Copy options */
str_options = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
@@ -968,25 +805,29 @@ nm_dhcp_client_handle_event(gpointer unused,
/* Create the IP config */
if (g_hash_table_size(str_options) > 0) {
- if (priv->addr_family == AF_INET) {
- ip_config = NM_IP_CONFIG_CAST(
- nm_dhcp_utils_ip4_config_from_options(nm_dhcp_client_get_multi_idx(self),
- priv->ifindex,
- priv->iface,
- str_options,
- priv->route_table,
- priv->route_metric));
+ if (priv->config.addr_family == AF_INET) {
+ l3cd = nm_dhcp_utils_ip4_config_from_options(
+ nm_l3cfg_get_multi_idx(priv->config.l3cfg),
+ nm_l3cfg_get_ifindex(priv->config.l3cfg),
+ priv->config.iface,
+ str_options);
} else {
- prefix = nm_dhcp_utils_ip6_prefix_from_options(str_options);
- ip_config = NM_IP_CONFIG_CAST(nm_dhcp_utils_ip6_config_from_options(
- nm_dhcp_client_get_multi_idx(self),
- priv->ifindex,
- priv->iface,
+ prefix = nm_dhcp_utils_ip6_prefix_from_options(str_options);
+ l3cd = nm_dhcp_utils_ip6_config_from_options(
+ nm_l3cfg_get_multi_idx(priv->config.l3cfg),
+ nm_l3cfg_get_ifindex(priv->config.l3cfg),
+ priv->config.iface,
str_options,
- NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY)));
+ priv->config.v6.info_only);
}
} else
g_warn_if_reached();
+
+ if (l3cd) {
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd,
+ priv->config.addr_family,
+ g_steal_pointer(&str_options));
+ }
}
if (!IN6_IS_ADDR_UNSPECIFIED(&prefix.address)) {
@@ -994,17 +835,16 @@ nm_dhcp_client_handle_event(gpointer unused,
* of the DHCP client instance. Instead, we just signal the prefix
* to the device. */
nm_dhcp_client_emit_ipv6_prefix_delegated(self, &prefix);
- } else {
- /* Fail if no valid IP config was received */
- if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED) && !ip_config) {
- _LOGW("client bound but IP config not received");
- new_state = NM_DHCP_STATE_FAIL;
- nm_clear_pointer(&str_options, g_hash_table_unref);
- }
+ return TRUE;
+ }
- nm_dhcp_client_set_state(self, new_state, ip_config, str_options);
+ /* Fail if no valid IP config was received */
+ if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED) && !l3cd) {
+ _LOGW("client bound but IP config not received");
+ new_state = NM_DHCP_STATE_FAIL;
}
+ nm_dhcp_client_set_state(self, new_state, l3cd);
return TRUE;
}
@@ -1016,18 +856,18 @@ nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer addr)
guint i;
/* IPv6 not implemented yet */
- nm_assert(priv->addr_family == AF_INET);
+ nm_assert(priv->config.addr_family == AF_INET);
- if (!priv->reject_servers || !priv->reject_servers[0])
+ if (!priv->config.reject_servers || !priv->config.reject_servers[0])
return FALSE;
- for (i = 0; priv->reject_servers[i]; i++) {
+ for (i = 0; priv->config.reject_servers[i]; i++) {
in_addr_t r_addr;
in_addr_t mask;
int r_prefix;
if (!nm_utils_parse_inaddr_prefix_bin(AF_INET,
- priv->reject_servers[i],
+ priv->config.reject_servers[i],
NULL,
&r_addr,
&r_prefix))
@@ -1040,146 +880,151 @@ nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer addr)
return FALSE;
}
-/*****************************************************************************/
+static void
+config_init(NMDhcpClientConfig *config, const NMDhcpClientConfig *src)
+{
+ *config = *src;
+
+ g_object_ref(config->l3cfg);
+
+ if (config->hwaddr)
+ g_bytes_ref(config->hwaddr);
+ if (config->bcast_hwaddr)
+ g_bytes_ref(config->bcast_hwaddr);
+ if (config->vendor_class_identifier)
+ g_bytes_ref(config->vendor_class_identifier);
+ if (config->client_id)
+ g_bytes_ref(config->client_id);
+
+ config->iface = g_strdup(config->iface);
+ config->uuid = g_strdup(config->uuid);
+ config->anycast_address = g_strdup(config->anycast_address);
+ config->hostname = g_strdup(config->hostname);
+ config->mud_url = g_strdup(config->mud_url);
+
+ config->reject_servers = (const char *const *) nm_strv_dup(config->reject_servers, -1, TRUE);
+
+ if (config->addr_family == AF_INET) {
+ config->v4.last_address = g_strdup(config->v4.last_address);
+ } else if (config->addr_family == AF_INET6) {
+ config->v6.ll_addr = g_memdup(config->v6.ll_addr, sizeof(struct in6_addr));
+ config->hwaddr = NULL;
+ config->bcast_hwaddr = NULL;
+ config->use_fqdn = TRUE;
+ } else {
+ nm_assert_not_reached();
+ }
+
+ if (!config->hostname && config->send_hostname) {
+ const char * hostname;
+ gs_free char *hostname_tmp = NULL;
+
+ hostname = nm_hostname_manager_get_hostname(nm_hostname_manager_get());
+
+ if (nm_utils_is_specific_hostname(hostname)) {
+ if (config->addr_family == AF_INET) {
+ char *dot;
+
+ hostname_tmp = g_strdup(hostname);
+ dot = strchr(hostname_tmp, '.');
+ if (dot)
+ *dot = '\0';
+ }
+ config->hostname = hostname_tmp ? g_steal_pointer(&hostname_tmp) : g_strdup(hostname);
+ }
+ }
+
+ if (config->hostname) {
+ if ((config->use_fqdn && !nm_sd_dns_name_is_valid(config->hostname))
+ || (!config->use_fqdn && !nm_sd_hostname_is_valid(config->hostname, FALSE))) {
+ nm_log_warn(LOGD_DHCP,
+ "dhcp%c: %s '%s' is invalid, will be ignored",
+ nm_utils_addr_family_to_char(config->addr_family),
+ config->use_fqdn ? "FQDN" : "hostname",
+ config->hostname);
+ nm_clear_g_free((gpointer *) &config->hostname);
+ }
+ }
+}
static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+config_clear(NMDhcpClientConfig *config)
{
- NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(object);
+ g_object_unref(config->l3cfg);
- switch (prop_id) {
- case PROP_IFACE:
- g_value_set_string(value, priv->iface);
- break;
- case PROP_IFINDEX:
- g_value_set_int(value, priv->ifindex);
- break;
- case PROP_HWADDR:
- g_value_set_boxed(value, priv->hwaddr);
- break;
- case PROP_BROADCAST_HWADDR:
- g_value_set_boxed(value, priv->bcast_hwaddr);
- break;
- case PROP_ADDR_FAMILY:
- g_value_set_int(value, priv->addr_family);
- break;
- case PROP_UUID:
- g_value_set_string(value, priv->uuid);
- break;
- case PROP_IAID:
- g_value_set_uint(value, priv->iaid);
- break;
- case PROP_IAID_EXPLICIT:
- g_value_set_boolean(value, priv->iaid_explicit);
- break;
- case PROP_HOSTNAME:
- g_value_set_string(value, priv->hostname);
- break;
- case PROP_ROUTE_METRIC:
- g_value_set_uint(value, priv->route_metric);
- break;
- case PROP_ROUTE_TABLE:
- g_value_set_uint(value, priv->route_table);
- break;
- case PROP_TIMEOUT:
- g_value_set_uint(value, priv->timeout);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
+ nm_clear_pointer(&config->hwaddr, g_bytes_unref);
+ nm_clear_pointer(&config->bcast_hwaddr, g_bytes_unref);
+ nm_clear_pointer(&config->vendor_class_identifier, g_bytes_unref);
+ nm_clear_pointer(&config->client_id, g_bytes_unref);
+
+ nm_clear_g_free((gpointer *) &config->iface);
+ nm_clear_g_free((gpointer *) &config->uuid);
+ nm_clear_g_free((gpointer *) &config->anycast_address);
+ nm_clear_g_free((gpointer *) &config->hostname);
+ nm_clear_g_free((gpointer *) &config->mud_url);
+
+ nm_clear_pointer((gpointer *) &config->reject_servers, g_strfreev);
+
+ if (config->addr_family == AF_INET) {
+ nm_clear_g_free((gpointer *) &config->v4.last_address);
+ } else if (config->addr_family == AF_INET6) {
+ nm_clear_g_free((gpointer *) &config->v6.ll_addr);
+ } else {
+ nm_assert_not_reached();
}
}
+int
+nm_dhcp_client_get_addr_family(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return priv->config.addr_family;
+}
+
+const char *
+nm_dhcp_client_get_iface(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return priv->config.iface;
+}
+
+NMDedupMultiIndex *
+nm_dhcp_client_get_multi_idx(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return nm_l3cfg_get_multi_idx(priv->config.l3cfg);
+}
+
+int
+nm_dhcp_client_get_ifindex(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return nm_l3cfg_get_ifindex(priv->config.l3cfg);
+}
+
+GBytes *
+nm_dhcp_client_get_effective_client_id(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return priv->effective_client_id;
+}
+
+/*****************************************************************************/
+
static void
set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(object);
- guint flags;
switch (prop_id) {
- case PROP_FLAGS:
- /* construct-only */
- flags = g_value_get_uint(value);
- nm_assert(!NM_FLAGS_ANY(flags, ~((guint) NM_DHCP_CLIENT_FLAGS_ALL)));
- priv->client_flags = flags;
- break;
- case PROP_MULTI_IDX:
- /* construct-only */
- priv->multi_idx = g_value_get_pointer(value);
- if (!priv->multi_idx)
- g_return_if_reached();
- nm_dedup_multi_index_ref(priv->multi_idx);
- break;
- case PROP_IFACE:
- /* construct-only */
- priv->iface = g_value_dup_string(value);
- g_return_if_fail(priv->iface);
- nm_assert(nm_utils_ifname_valid_kernel(priv->iface, NULL));
- break;
- case PROP_IFINDEX:
- /* construct-only */
- priv->ifindex = g_value_get_int(value);
- g_return_if_fail(priv->ifindex > 0);
- break;
- case PROP_HWADDR:
- /* construct-only */
- priv->hwaddr = g_value_dup_boxed(value);
- break;
- case PROP_ANYCAST_ADDRESS:
- /* construct-only */
- priv->anycast_address = g_value_dup_string(value);
- break;
- case PROP_BROADCAST_HWADDR:
- /* construct-only */
- priv->bcast_hwaddr = g_value_dup_boxed(value);
- break;
- case PROP_ADDR_FAMILY:
- /* construct-only */
- priv->addr_family = g_value_get_int(value);
- if (!NM_IN_SET(priv->addr_family, AF_INET, AF_INET6))
- g_return_if_reached();
- break;
- case PROP_UUID:
- /* construct-only */
- priv->uuid = g_value_dup_string(value);
- break;
- case PROP_IAID:
- /* construct-only */
- priv->iaid = g_value_get_uint(value);
- break;
- case PROP_IAID_EXPLICIT:
- /* construct-only */
- priv->iaid_explicit = g_value_get_boolean(value);
- break;
- case PROP_HOSTNAME:
- /* construct-only */
- priv->hostname = g_value_dup_string(value);
- break;
- case PROP_HOSTNAME_FLAGS:
- /* construct-only */
- priv->hostname_flags = g_value_get_uint(value);
- break;
- case PROP_MUD_URL:
- /* construct-only */
- priv->mud_url = g_value_dup_string(value);
- break;
- case PROP_ROUTE_TABLE:
- priv->route_table = g_value_get_uint(value);
- break;
- case PROP_ROUTE_METRIC:
- priv->route_metric = g_value_get_uint(value);
- break;
- case PROP_TIMEOUT:
- /* construct-only */
- priv->timeout = g_value_get_uint(value);
- break;
- case PROP_VENDOR_CLASS_IDENTIFIER:
- /* construct-only */
- priv->vendor_class_identifier = g_value_dup_boxed(value);
- break;
- case PROP_REJECT_SERVERS:
+ case PROP_CONFIG:
/* construct-only */
- priv->reject_servers = nm_strv_dup_packed(g_value_get_boxed(value), -1);
+ config_init(&priv->config, g_value_get_pointer(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -1200,53 +1045,31 @@ nm_dhcp_client_init(NMDhcpClient *self)
priv->pid = -1;
}
-#if NM_MORE_ASSERTS
static void
-constructed(GObject *object)
+dispose(GObject *object)
{
NMDhcpClient * self = NM_DHCP_CLIENT(object);
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
- /* certain flags only make sense with certain address family. Assert
- * for that. */
- if (NM_IS_IPv4(priv->addr_family))
- nm_assert(!NM_FLAGS_ANY(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY));
- else {
- nm_assert(NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN));
- nm_assert(!NM_FLAGS_ANY(priv->client_flags, NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST));
- }
+ nm_dhcp_client_stop(self, FALSE);
- nm_assert(!priv->anycast_address || nm_utils_hwaddr_valid(priv->anycast_address, ETH_ALEN));
+ watch_cleanup(self);
+ timeout_cleanup(self);
+
+ nm_clear_g_source_inst(&priv->no_lease_timeout_source);
- G_OBJECT_CLASS(nm_dhcp_client_parent_class)->constructed(object);
+ G_OBJECT_CLASS(nm_dhcp_client_parent_class)->dispose(object);
}
-#endif
static void
-dispose(GObject *object)
+finalize(GObject *object)
{
NMDhcpClient * self = NM_DHCP_CLIENT(object);
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
- nm_dhcp_client_stop(self, FALSE);
-
- watch_cleanup(self);
- timeout_cleanup(self);
-
- nm_clear_g_free(&priv->iface);
- nm_clear_g_free(&priv->hostname);
- nm_clear_g_free(&priv->uuid);
- nm_clear_g_free(&priv->anycast_address);
- nm_clear_g_free(&priv->mud_url);
- nm_clear_g_free(&priv->reject_servers);
- nm_clear_pointer(&priv->client_id, g_bytes_unref);
- nm_clear_pointer(&priv->hwaddr, g_bytes_unref);
- nm_clear_pointer(&priv->bcast_hwaddr, g_bytes_unref);
- nm_clear_pointer(&priv->vendor_class_identifier, g_bytes_unref);
+ config_clear(&priv->config);
- G_OBJECT_CLASS(nm_dhcp_client_parent_class)->dispose(object);
-
- priv->multi_idx = nm_dedup_multi_index_unref(priv->multi_idx);
+ G_OBJECT_CLASS(nm_dhcp_client_parent_class)->finalize(object);
}
static void
@@ -1256,165 +1079,19 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class)
g_type_class_add_private(client_class, sizeof(NMDhcpClientPrivate));
-#if NM_MORE_ASSERTS
- object_class->constructed = constructed;
-#endif
object_class->dispose = dispose;
- object_class->get_property = get_property;
+ object_class->finalize = finalize;
object_class->set_property = set_property;
client_class->stop = stop;
client_class->get_duid = get_duid;
- obj_properties[PROP_MULTI_IDX] =
- g_param_spec_pointer(NM_DHCP_CLIENT_MULTI_IDX,
+ obj_properties[PROP_CONFIG] =
+ g_param_spec_pointer(NM_DHCP_CLIENT_CONFIG,
"",
"",
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IFACE] =
- g_param_spec_string(NM_DHCP_CLIENT_INTERFACE,
- "",
- "",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_IFINDEX] =
- g_param_spec_int(NM_DHCP_CLIENT_IFINDEX,
- "",
- "",
- -1,
- G_MAXINT,
- -1,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_HWADDR] =
- g_param_spec_boxed(NM_DHCP_CLIENT_HWADDR,
- "",
- "",
- G_TYPE_BYTES,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_BROADCAST_HWADDR] =
- g_param_spec_boxed(NM_DHCP_CLIENT_BROADCAST_HWADDR,
- "",
- "",
- G_TYPE_BYTES,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_ADDR_FAMILY] =
- g_param_spec_int(NM_DHCP_CLIENT_ADDR_FAMILY,
- "",
- "",
- 0,
- G_MAXINT,
- AF_UNSPEC,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_ANYCAST_ADDRESS] =
- g_param_spec_string(NM_DHCP_CLIENT_ANYCAST_ADDRESS,
- "",
- "",
- NULL,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_UUID] =
- g_param_spec_string(NM_DHCP_CLIENT_UUID,
- "",
- "",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_IAID] =
- g_param_spec_uint(NM_DHCP_CLIENT_IAID,
- "",
- "",
- 0,
- G_MAXUINT32,
- 0,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_IAID_EXPLICIT] =
- g_param_spec_boolean(NM_DHCP_CLIENT_IAID_EXPLICIT,
- "",
- "",
- FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_HOSTNAME] =
- g_param_spec_string(NM_DHCP_CLIENT_HOSTNAME,
- "",
- "",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_HOSTNAME_FLAGS] =
- g_param_spec_uint(NM_DHCP_CLIENT_HOSTNAME_FLAGS,
- "",
- "",
- 0,
- G_MAXUINT32,
- NM_DHCP_HOSTNAME_FLAG_NONE,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_MUD_URL] =
- g_param_spec_string(NM_DHCP_CLIENT_MUD_URL,
- "",
- "",
- NULL,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_ROUTE_TABLE] =
- g_param_spec_uint(NM_DHCP_CLIENT_ROUTE_TABLE,
- "",
- "",
- 0,
- G_MAXUINT32,
- RT_TABLE_MAIN,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_ROUTE_METRIC] =
- g_param_spec_uint(NM_DHCP_CLIENT_ROUTE_METRIC,
- "",
- "",
- 0,
- G_MAXUINT32,
- 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- G_STATIC_ASSERT_EXPR(G_MAXINT32 == NM_DHCP_TIMEOUT_INFINITY);
- obj_properties[PROP_TIMEOUT] =
- g_param_spec_uint(NM_DHCP_CLIENT_TIMEOUT,
- "",
- "",
- 1,
- G_MAXINT32,
- NM_DHCP_TIMEOUT_DEFAULT,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_FLAGS] =
- g_param_spec_uint(NM_DHCP_CLIENT_FLAGS,
- "",
- "",
- 0,
- G_MAXUINT32,
- 0,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_VENDOR_CLASS_IDENTIFIER] =
- g_param_spec_boxed(NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER,
- "",
- "",
- G_TYPE_BYTES,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_REJECT_SERVERS] =
- g_param_spec_boxed(NM_DHCP_CLIENT_REJECT_SERVERS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
signals[SIGNAL_NOTIFY] =
diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h
index 2e7e021650..372acc752c 100644
--- a/src/core/dhcp/nm-dhcp-client.h
+++ b/src/core/dhcp/nm-dhcp-client.h
@@ -8,8 +8,6 @@
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "nm-dhcp-utils.h"
#define NM_DHCP_TIMEOUT_DEFAULT ((guint32) 45) /* default DHCP timeout, in seconds */
@@ -24,25 +22,7 @@
#define NM_DHCP_CLIENT_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_CLIENT, NMDhcpClientClass))
-#define NM_DHCP_CLIENT_ADDR_FAMILY "addr-family"
-#define NM_DHCP_CLIENT_ANYCAST_ADDRESS "anycast-address"
-#define NM_DHCP_CLIENT_FLAGS "flags"
-#define NM_DHCP_CLIENT_HWADDR "hwaddr"
-#define NM_DHCP_CLIENT_BROADCAST_HWADDR "broadcast-hwaddr"
-#define NM_DHCP_CLIENT_IFINDEX "ifindex"
-#define NM_DHCP_CLIENT_INTERFACE "iface"
-#define NM_DHCP_CLIENT_MULTI_IDX "multi-idx"
-#define NM_DHCP_CLIENT_HOSTNAME "hostname"
-#define NM_DHCP_CLIENT_MUD_URL "mud-url"
-#define NM_DHCP_CLIENT_ROUTE_METRIC "route-metric"
-#define NM_DHCP_CLIENT_ROUTE_TABLE "route-table"
-#define NM_DHCP_CLIENT_TIMEOUT "timeout"
-#define NM_DHCP_CLIENT_UUID "uuid"
-#define NM_DHCP_CLIENT_IAID "iaid"
-#define NM_DHCP_CLIENT_IAID_EXPLICIT "iaid-explicit"
-#define NM_DHCP_CLIENT_HOSTNAME_FLAGS "hostname-flags"
-#define NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER "vendor-class-identifier"
-#define NM_DHCP_CLIENT_REJECT_SERVERS "reject-servers"
+#define NM_DHCP_CLIENT_CONFIG "config"
#define NM_DHCP_CLIENT_NOTIFY "dhcp-notify"
@@ -59,7 +39,27 @@ typedef enum {
} NMDhcpState;
typedef enum _nm_packed {
- NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED,
+ NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE,
+
+ /* When NM_DHCP_CLIENT_NO_LEASE_TIMEOUT expired and the state
+ * switched from NM_DHCP_CLIENT_STATE_NO_LEASE to
+ * NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT. */
+ NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT,
+
+ /* NMDhcpClient will indefinitely try to get/renew the lease.
+ * As such, it's never officially in a non-recoverable state.
+ * However, there are cases when it really looks like we won't
+ * be able to get a lease. For example, if the underlying interface
+ * is layer 3 only, if we have no IPv6 link local address for a prolonged
+ * time, or if dhclient is not installed.
+ * But even these cases are potentially recoverable. This is only
+ * a hint to the user (which they might ignore).
+ *
+ * In particular, NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT might mean
+ * that the DHCP is currently not running, but that could change
+ * at any moment and from client's side, it does not look bad. */
+ NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD,
+
NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED,
} NMDhcpClientNotifyType;
@@ -67,18 +67,126 @@ typedef struct {
NMDhcpClientNotifyType notify_type;
union {
struct {
- NMIPConfig *ip_config;
- GHashTable *options;
- NMDhcpState dhcp_state;
- } state_changed;
+ /* This is either the new lease information we just received,
+ * or NULL (if a previous lease timed out). It can also be the
+ * previous lease, that was injected. */
+ const NML3ConfigData *l3cd;
+ } lease_update;
struct {
const NMPlatformIP6Address *prefix;
} prefix_delegated;
+ struct {
+ const char *reason;
+ } it_looks_bad;
};
} NMDhcpClientNotifyData;
const char *nm_dhcp_state_to_string(NMDhcpState state);
+/* FIXME(l3cfg:dhcp:config): nm_dhcp_manager_start_ip[46]() has a gazillion of parameters,
+ * those get passed on as CONSTRUCT_ONLY properties to the NMDhcpClient. Drop
+ * all these parameters, and let the caller provide one NMDhcpClientConfig
+ * instance. There will be only one GObject property (NM_DHCP_CLIENT_CONFIG),
+ * which is CONSTRUCT_ONLY and takes a (mandatory) G_TYPE_POINTER for the
+ * configuration.
+ *
+ * Since NMDhcpClientConfig has an addr_family, we also don't need separate
+ * nm_dhcp_manager_start_ip[46]() methods. */
+typedef struct {
+ int addr_family;
+
+ /* The NML3Cfg instance is the manager object for the ifindex on which
+ * NMDhcpClient is supposed to run. */
+ NML3Cfg *l3cfg;
+
+ /* FIXME(l3cfg:dhcp:previous-lease): most parameters of NMDhcpClient are immutable,
+ * so to change them (during reapply), we need to create and start
+ * a new NMDhcpClient instance.
+ *
+ * However, while the restart happens, we want to stick to the previous
+ * lease (if any). Allow the caller to provide such a previous lease,
+ * and if present, the instance starts by pretending that it just received
+ * this lease, before really starting. */
+ const NML3ConfigData *previous_lease;
+
+ const char *iface;
+
+ /* The hardware address */
+ GBytes *hwaddr;
+
+ /* The broadcast hardware address */
+ GBytes *bcast_hwaddr;
+
+ /* Timeout in seconds before reporting failure */
+ guint32 timeout;
+
+ /* Flags for the hostname and FQDN DHCP options */
+ NMDhcpHostnameFlags hostname_flags;
+
+ /* The UUID of the connection. Used mainly to build
+ * lease file names. */
+ const char *uuid;
+
+ /* Set to reduce the number of broadcast packets when the
+ * anycast hardware address of the DHCP service is known. */
+ const char *anycast_address;
+
+ /* The hostname or FQDN to send. */
+ const char *hostname;
+
+ /* The Manufacturer Usage Description (RFC 8520) URL to send */
+ const char *mud_url;
+
+ /* The value for the Vendor Class Identifier option */
+ GBytes *vendor_class_identifier;
+
+ /* A list of servers from which offers should be rejected */
+ const char *const *reject_servers;
+
+ /* The client identifier (DHCPv4) or DUID (DHCPv6) to send */
+ GBytes *client_id;
+
+ /* Whether to send the hostname or FQDN option */
+ bool send_hostname : 1;
+
+ /* Whether to send the hostname as HOSTNAME option or FQDN.
+ * For DHCPv6 this is always TRUE. */
+ bool use_fqdn : 1;
+
+ union {
+ struct {
+ /* Set BOOTP broadcast flag in request packets, so that servers
+ * will always broadcast replies. */
+ bool request_broadcast : 1;
+
+ /* The address from the previous lease */
+ const char *last_address;
+ } v4;
+ struct {
+ /* The link-local IPv6 address for UDP socket bind() */
+ const struct in6_addr *ll_addr;
+
+ /* If set, the DUID from the connection is used; otherwise
+ * the one from an existing lease is used. */
+ gboolean enforce_duid;
+
+ /* The IAID to use */
+ guint32 iaid;
+
+ /* Whether the IAID was explicitly set in the connection or
+ * as global default */
+ gboolean iaid_explicit;
+
+ /* Number to prefixes (IA_PD) to request */
+ guint needed_prefixes;
+
+ /* Use Information-request to get stateless configuration
+ * parameters (don't request a IA_NA) */
+ bool info_only : 1;
+ } v6;
+ };
+} NMDhcpClientConfig;
+
struct _NMDhcpClientPrivate;
typedef struct {
@@ -100,17 +208,13 @@ typedef enum _nm_packed {
typedef struct {
GObjectClass parent;
- gboolean (*ip4_start)(NMDhcpClient *self, const char *last_ip4_address, GError **error);
+ gboolean (*ip4_start)(NMDhcpClient *self, GError **error);
gboolean (*accept)(NMDhcpClient *self, GError **error);
gboolean (*decline)(NMDhcpClient *self, const char *error_message, GError **error);
- gboolean (*ip6_start)(NMDhcpClient * self,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error);
+ gboolean (*ip6_start)(NMDhcpClient *self, GError **error);
void (*stop)(NMDhcpClient *self, gboolean release);
@@ -128,64 +232,25 @@ typedef struct {
GType nm_dhcp_client_get_type(void);
-struct _NMDedupMultiIndex *nm_dhcp_client_get_multi_idx(NMDhcpClient *self);
-
-pid_t nm_dhcp_client_get_pid(NMDhcpClient *self);
-
-int nm_dhcp_client_get_addr_family(NMDhcpClient *self);
-
-const char *nm_dhcp_client_get_iface(NMDhcpClient *self);
-
-int nm_dhcp_client_get_ifindex(NMDhcpClient *self);
-
-const char *nm_dhcp_client_get_uuid(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_duid(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_hw_addr(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self);
-
-const char *nm_dhcp_client_get_anycast_address(NMDhcpClient *self);
-
-guint32 nm_dhcp_client_get_route_table(NMDhcpClient *self);
-
-void nm_dhcp_client_set_route_table(NMDhcpClient *self, guint32 route_table);
+gboolean nm_dhcp_client_start_ip4(NMDhcpClient *self, GError **error);
+gboolean nm_dhcp_client_start_ip6(NMDhcpClient *self, GError **error);
-guint32 nm_dhcp_client_get_route_metric(NMDhcpClient *self);
+const NMDhcpClientConfig *nm_dhcp_client_get_config(NMDhcpClient *self);
-void nm_dhcp_client_set_route_metric(NMDhcpClient *self, guint32 route_metric);
-
-guint32 nm_dhcp_client_get_timeout(NMDhcpClient *self);
-
-guint32 nm_dhcp_client_get_iaid(NMDhcpClient *self);
-
-gboolean nm_dhcp_client_get_iaid_explicit(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_client_id(NMDhcpClient *self);
-
-const char * nm_dhcp_client_get_hostname(NMDhcpClient *self);
-const char * nm_dhcp_client_get_mud_url(NMDhcpClient *self);
-const char *const *nm_dhcp_client_get_reject_servers(NMDhcpClient *self);
-
-NMDhcpHostnameFlags nm_dhcp_client_get_hostname_flags(NMDhcpClient *self);
-
-NMDhcpClientFlags nm_dhcp_client_get_client_flags(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_vendor_class_identifier(NMDhcpClient *self);
-
-gboolean nm_dhcp_client_start_ip4(NMDhcpClient *self,
- GBytes * client_id,
- const char * last_ip4_address,
- GError ** error);
+pid_t nm_dhcp_client_get_pid(NMDhcpClient *self);
-gboolean nm_dhcp_client_start_ip6(NMDhcpClient * self,
- GBytes * client_id,
- gboolean enforce_duid,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error);
+static inline const NML3ConfigData *
+nm_dhcp_client_get_lease(NMDhcpClient *self)
+{
+ /* FIXME(l3cfg:dhcp:previous-lease): this function returns the currently
+ * valid, exposed lease.
+ *
+ * Note that NMDhcpClient should accept as construct argument a *previous* lease,
+ * and (if that lease is still valid), pretend that it's good to use. The point is
+ * so that during reapply we keep using the current address, until a new lease
+ * was received. */
+ return NULL;
+}
gboolean nm_dhcp_client_accept(NMDhcpClient *self, GError **error);
gboolean nm_dhcp_client_can_accept(NMDhcpClient *self);
@@ -205,10 +270,8 @@ void nm_dhcp_client_watch_child(NMDhcpClient *self, pid_t pid);
void nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid);
-void nm_dhcp_client_set_state(NMDhcpClient *self,
- NMDhcpState new_state,
- NMIPConfig * ip_config,
- GHashTable * options); /* str:str hash */
+void
+nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, const NML3ConfigData *l3cd);
gboolean nm_dhcp_client_handle_event(gpointer unused,
const char * iface,
@@ -217,17 +280,19 @@ gboolean nm_dhcp_client_handle_event(gpointer unused,
const char * reason,
NMDhcpClient *self);
-void nm_dhcp_client_set_client_id(NMDhcpClient *self, GBytes *client_id);
-void nm_dhcp_client_set_client_id_bin(NMDhcpClient *self,
- guint8 type,
- const guint8 *client_id,
- gsize len);
-
void nm_dhcp_client_emit_ipv6_prefix_delegated(NMDhcpClient * self,
const NMPlatformIP6Address *prefix);
gboolean nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer addr);
+int nm_dhcp_client_get_addr_family(NMDhcpClient *self);
+const char * nm_dhcp_client_get_iface(NMDhcpClient *self);
+NMDedupMultiIndex *nm_dhcp_client_get_multi_idx(NMDhcpClient *self);
+int nm_dhcp_client_get_ifindex(NMDhcpClient *self);
+
+void nm_dhcp_client_set_effective_client_id(NMDhcpClient *self, GBytes *client_id);
+GBytes *nm_dhcp_client_get_effective_client_id(NMDhcpClient *self);
+
/*****************************************************************************
* Client data
*****************************************************************************/
diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.c b/src/core/dhcp/nm-dhcp-dhclient-utils.c
index 341ac7b2fa..60cb46e507 100644
--- a/src/core/dhcp/nm-dhcp-dhclient-utils.c
+++ b/src/core/dhcp/nm-dhcp-dhclient-utils.c
@@ -15,7 +15,6 @@
#include "libnm-glib-aux/nm-dedup-multi.h"
#include "nm-dhcp-utils.h"
-#include "nm-ip4-config.h"
#include "nm-utils.h"
#include "libnm-platform/nm-platform.h"
#include "NetworkManagerUtils.h"
diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c
index 970a51f5dd..9406ae7005 100644
--- a/src/core/dhcp/nm-dhcp-dhclient.c
+++ b/src/core/dhcp/nm-dhcp-dhclient.c
@@ -333,26 +333,28 @@ dhclient_start(NMDhcpClient *client,
const char * mode_opt,
gboolean release,
pid_t * out_pid,
- int prefixes,
GError ** error)
{
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
gs_unref_ptrarray GPtrArray *argv = NULL;
pid_t pid;
- gs_free_error GError *local = NULL;
- const char * iface;
- const char * uuid;
- const char * system_bus_address;
- const char * dhclient_path;
- char * binary_name;
- gs_free char * cmd_str = NULL;
- gs_free char * pid_file = NULL;
- gs_free char * system_bus_address_env = NULL;
- gs_free char * preferred_leasefile_path = NULL;
- const int addr_family = nm_dhcp_client_get_addr_family(client);
+ gs_free_error GError * local = NULL;
+ const char * iface;
+ const char * uuid;
+ const char * system_bus_address;
+ const char * dhclient_path;
+ char * binary_name;
+ gs_free char * cmd_str = NULL;
+ gs_free char * pid_file = NULL;
+ gs_free char * system_bus_address_env = NULL;
+ gs_free char * preferred_leasefile_path = NULL;
+ int addr_family;
+ const NMDhcpClientConfig *client_config;
g_return_val_if_fail(!priv->pid_file, FALSE);
+ client_config = nm_dhcp_client_get_config(client);
+ addr_family = client_config->addr_family;
NM_SET_OUT(out_pid, 0);
@@ -362,8 +364,8 @@ dhclient_start(NMDhcpClient *client,
return FALSE;
}
- iface = nm_dhcp_client_get_iface(client);
- uuid = nm_dhcp_client_get_uuid(client);
+ iface = client_config->iface;
+ uuid = client_config->uuid;
pid_file = g_strdup_printf(NMRUNDIR "/dhclient%s-%s.pid",
_addr_family_to_path_part(addr_family),
@@ -409,9 +411,7 @@ dhclient_start(NMDhcpClient *client,
/* Save the DUID to the leasefile dhclient will actually use */
if (addr_family == AF_INET6) {
- if (!nm_dhcp_dhclient_save_duid(priv->lease_file,
- nm_dhcp_client_get_client_id(client),
- &local)) {
+ if (!nm_dhcp_dhclient_save_duid(priv->lease_file, client_config->client_id, &local)) {
nm_utils_error_set(error,
NM_UTILS_ERROR_UNKNOWN,
"failed to save DUID to '%s': %s",
@@ -434,13 +434,13 @@ dhclient_start(NMDhcpClient *client,
if (release)
g_ptr_array_add(argv, (gpointer) "-r");
- if (!release
- && NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
- NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST)) {
+ if (!release && client_config->addr_family == AF_INET && client_config->v4.request_broadcast) {
g_ptr_array_add(argv, (gpointer) "-B");
}
if (addr_family == AF_INET6) {
+ guint prefixes = client_config->v6.needed_prefixes;
+
g_ptr_array_add(argv, (gpointer) "-6");
if (prefixes > 0 && nm_streq0(mode_opt, "-S")) {
@@ -513,29 +513,28 @@ dhclient_start(NMDhcpClient *client,
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
- NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
- NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
- GBytes * client_id;
- gs_unref_bytes GBytes *new_client_id = NULL;
-
- client_id = nm_dhcp_client_get_client_id(client);
-
- priv->conf_file = create_dhclient_config(
- self,
- AF_INET,
- nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
- client_id,
- nm_dhcp_client_get_anycast_address(client),
- nm_dhcp_client_get_hostname(client),
- nm_dhcp_client_get_timeout(client),
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN),
- nm_dhcp_client_get_hostname_flags(client),
- nm_dhcp_client_get_mud_url(client),
- nm_dhcp_client_get_reject_servers(client),
- &new_client_id);
+ NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
+ NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
+ gs_unref_bytes GBytes * new_client_id = NULL;
+ const NMDhcpClientConfig *client_config;
+
+ client_config = nm_dhcp_client_get_config(client);
+
+ priv->conf_file = create_dhclient_config(self,
+ AF_INET,
+ client_config->iface,
+ client_config->uuid,
+ client_config->client_id,
+ client_config->anycast_address,
+ client_config->hostname,
+ client_config->timeout,
+ client_config->use_fqdn,
+ client_config->hostname_flags,
+ client_config->mud_url,
+ client_config->reject_servers,
+ &new_client_id);
if (!priv->conf_file) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_UNKNOWN,
@@ -544,36 +543,35 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
if (new_client_id) {
- nm_assert(!client_id);
- nm_dhcp_client_set_client_id(client, new_client_id);
+ nm_assert(!client_config->client_id);
+ nm_dhcp_client_set_effective_client_id(client, new_client_id);
}
- return dhclient_start(client, NULL, FALSE, NULL, 0, error);
+ return dhclient_start(client, NULL, FALSE, NULL, error);
}
static gboolean
-ip6_start(NMDhcpClient * client,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error)
+ip6_start(NMDhcpClient *client, GError **error)
{
- NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
- NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
+ NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
+ NMDhcpDhclientPrivate * priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
+ const NMDhcpClientConfig *config;
- if (nm_dhcp_client_get_iaid_explicit(client))
+ config = nm_dhcp_client_get_config(client);
+
+ if (config->v6.iaid_explicit)
_LOGW("dhclient does not support specifying an IAID for DHCPv6, it will be ignored");
priv->conf_file = create_dhclient_config(self,
AF_INET6,
- nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
+ config->iface,
+ config->uuid,
NULL,
- nm_dhcp_client_get_anycast_address(client),
- nm_dhcp_client_get_hostname(client),
- nm_dhcp_client_get_timeout(client),
+ config->anycast_address,
+ config->hostname,
+ config->timeout,
TRUE,
- nm_dhcp_client_get_hostname_flags(client),
- nm_dhcp_client_get_mud_url(client),
+ config->hostname_flags,
+ config->mud_url,
NULL,
NULL);
if (!priv->conf_file) {
@@ -583,15 +581,7 @@ ip6_start(NMDhcpClient * client,
return FALSE;
}
- return dhclient_start(client,
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
- NM_DHCP_CLIENT_FLAGS_INFO_ONLY)
- ? "-S"
- : "-N",
- FALSE,
- NULL,
- needed_prefixes,
- error);
+ return dhclient_start(client, config->v6.needed_prefixes ? "-S" : "-N", FALSE, NULL, error);
}
static void
@@ -625,7 +615,7 @@ stop(NMDhcpClient *client, gboolean release)
if (release) {
pid_t rpid = -1;
- if (dhclient_start(client, NULL, TRUE, &rpid, 0, NULL)) {
+ if (dhclient_start(client, NULL, TRUE, &rpid, NULL)) {
/* Wait a few seconds for the release to happen */
nm_dhcp_client_stop_pid(rpid, nm_dhcp_client_get_iface(client));
}
@@ -635,16 +625,19 @@ stop(NMDhcpClient *client, gboolean release)
static GBytes *
get_duid(NMDhcpClient *client)
{
- NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
- NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
- GBytes * duid = NULL;
- gs_free char * leasefile = NULL;
- GError * error = NULL;
+ NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
+ NMDhcpDhclientPrivate * priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
+ const NMDhcpClientConfig *client_config;
+ GBytes * duid = NULL;
+ gs_free char * leasefile = NULL;
+ GError * error = NULL;
+
+ client_config = nm_dhcp_client_get_config(client);
/* Look in interface-specific leasefile first for backwards compat */
leasefile = get_dhclient_leasefile(AF_INET6,
nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
+ client_config->uuid,
NULL);
if (leasefile) {
_LOGD("looking for DUID in '%s'", leasefile);
diff --git a/src/core/dhcp/nm-dhcp-dhcpcanon.c b/src/core/dhcp/nm-dhcp-dhcpcanon.c
index f993ffb940..ed29b85cd0 100644
--- a/src/core/dhcp/nm-dhcp-dhcpcanon.c
+++ b/src/core/dhcp/nm-dhcp-dhcpcanon.c
@@ -160,7 +160,7 @@ dhcpcanon_start(NMDhcpClient *client,
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
return dhcpcanon_start(client, NULL, NULL, FALSE, NULL, 0, error);
}
diff --git a/src/core/dhcp/nm-dhcp-dhcpcd.c b/src/core/dhcp/nm-dhcp-dhcpcd.c
index 7522156bef..0a6a91b743 100644
--- a/src/core/dhcp/nm-dhcp-dhcpcd.c
+++ b/src/core/dhcp/nm-dhcp-dhcpcd.c
@@ -64,21 +64,19 @@ nm_dhcp_dhcpcd_get_path(void)
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
- NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client);
+ NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client);
+ const NMDhcpClientConfig *client_config;
gs_unref_ptrarray GPtrArray *argv = NULL;
pid_t pid;
GError * local;
gs_free char * cmd_str = NULL;
- const char * iface;
const char * dhcpcd_path;
- const char * hostname;
pid = nm_dhcp_client_get_pid(client);
g_return_val_if_fail(pid == -1, FALSE);
-
- iface = nm_dhcp_client_get_iface(client);
+ client_config = nm_dhcp_client_get_config(client);
dhcpcd_path = nm_dhcp_dhcpcd_get_path();
if (!dhcpcd_path) {
@@ -115,21 +113,19 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
*/
g_ptr_array_add(argv, (gpointer) "-4");
- hostname = nm_dhcp_client_get_hostname(client);
-
- if (hostname) {
- if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN)) {
+ if (client_config->hostname) {
+ if (client_config->use_fqdn) {
g_ptr_array_add(argv, (gpointer) "-h");
- g_ptr_array_add(argv, (gpointer) hostname);
+ g_ptr_array_add(argv, (gpointer) client_config->hostname);
g_ptr_array_add(argv, (gpointer) "-F");
g_ptr_array_add(argv, (gpointer) "both");
} else {
g_ptr_array_add(argv, (gpointer) "-h");
- g_ptr_array_add(argv, (gpointer) hostname);
+ g_ptr_array_add(argv, (gpointer) client_config->hostname);
}
}
- g_ptr_array_add(argv, (gpointer) iface);
+ g_ptr_array_add(argv, (gpointer) client_config->iface);
g_ptr_array_add(argv, NULL);
_LOGD("running: %s", (cmd_str = g_strjoinv(" ", (char **) argv->pdata)));
diff --git a/src/core/dhcp/nm-dhcp-manager.c b/src/core/dhcp/nm-dhcp-manager.c
index 3cb893932d..7c7ac13f33 100644
--- a/src/core/dhcp/nm-dhcp-manager.c
+++ b/src/core/dhcp/nm-dhcp-manager.c
@@ -17,7 +17,6 @@
#include <stdio.h>
#include "libnm-glib-aux/nm-dedup-multi.h"
-#include "libnm-systemd-shared/nm-sd-utils-shared.h"
#include "nm-config.h"
#include "NetworkManagerUtils.h"
@@ -26,7 +25,6 @@
typedef struct {
const NMDhcpClientFactory *client_factory;
- char * default_hostname;
} NMDhcpManagerPrivate;
struct _NMDhcpManager {
@@ -129,34 +127,8 @@ _client_factory_get_gtype(const NMDhcpClientFactory *client_factory, int addr_fa
/*****************************************************************************/
-static NMDhcpClient *
-client_start(NMDhcpManager * self,
- int addr_family,
- NMDedupMultiIndex * multi_idx,
- const char * iface,
- int ifindex,
- GBytes * hwaddr,
- GBytes * bcast_hwaddr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- const struct in6_addr * ipv6_ll_addr,
- GBytes * dhcp_client_id,
- gboolean enforce_duid,
- guint32 iaid,
- gboolean iaid_explicit,
- guint32 timeout,
- NMDhcpClientFlags client_flags,
- const char * anycast_address,
- const char * hostname,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- NMSettingIP6ConfigPrivacy privacy,
- const char * last_ip4_address,
- guint needed_prefixes,
- GBytes * vendor_class_identifier,
- const char *const * reject_servers,
- GError ** error)
+NMDhcpClient *
+nm_dhcp_manager_start_client(NMDhcpManager *self, NMDhcpClientConfig *config, GError **error)
{
NMDhcpManagerPrivate *priv;
gs_unref_object NMDhcpClient *client = NULL;
@@ -165,100 +137,44 @@ client_start(NMDhcpManager * self,
GType gtype;
g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL);
- g_return_val_if_fail(iface, NULL);
- g_return_val_if_fail(ifindex > 0, NULL);
- g_return_val_if_fail(uuid != NULL, NULL);
- g_return_val_if_fail(!dhcp_client_id || g_bytes_get_size(dhcp_client_id) >= 2, NULL);
- g_return_val_if_fail(!vendor_class_identifier
- || g_bytes_get_size(vendor_class_identifier) <= 255,
+ g_return_val_if_fail(config, NULL);
+ g_return_val_if_fail(config->iface, NULL);
+ g_return_val_if_fail(config->l3cfg, NULL);
+ g_return_val_if_fail(config->uuid != NULL, NULL);
+ g_return_val_if_fail(!config->client_id || g_bytes_get_size(config->client_id) >= 2, NULL);
+ g_return_val_if_fail(!config->vendor_class_identifier
+ || g_bytes_get_size(config->vendor_class_identifier) <= 255,
NULL);
g_return_val_if_fail(!error || !*error, NULL);
- nm_assert(!NM_FLAGS_ANY(client_flags, ~NM_DHCP_CLIENT_FLAGS_ALL));
- if (addr_family == AF_INET) {
- if (!hwaddr || !bcast_hwaddr) {
+ if (config->addr_family == AF_INET) {
+ if (!config->hwaddr || !config->bcast_hwaddr) {
nm_utils_error_set(error,
NM_UTILS_ERROR_UNKNOWN,
"missing %s address",
- hwaddr ? "broadcast" : "MAC");
+ config->hwaddr ? "broadcast" : "MAC");
return NULL;
}
- hwaddr_len = g_bytes_get_size(hwaddr);
+ hwaddr_len = g_bytes_get_size(config->hwaddr);
if (hwaddr_len == 0 || hwaddr_len > _NM_UTILS_HWADDR_LEN_MAX) {
nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
g_return_val_if_reached(NULL);
}
- nm_assert(g_bytes_get_size(hwaddr) == g_bytes_get_size(bcast_hwaddr));
- } else {
- hwaddr = NULL;
- bcast_hwaddr = NULL;
- }
-
- if (hostname) {
- gboolean use_fqdn = NM_FLAGS_HAS(client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN);
-
- if ((use_fqdn && !nm_sd_dns_name_is_valid(hostname))
- || (!use_fqdn && !nm_sd_hostname_is_valid(hostname, FALSE))) {
- nm_log_warn(LOGD_DHCP,
- "dhcp%c: %s '%s' is invalid, will be ignored",
- nm_utils_addr_family_to_char(addr_family),
- use_fqdn ? "FQDN" : "hostname",
- hostname);
- hostname = NULL;
- }
+ nm_assert(g_bytes_get_size(config->hwaddr) == g_bytes_get_size(config->bcast_hwaddr));
}
priv = NM_DHCP_MANAGER_GET_PRIVATE(self);
- gtype = _client_factory_get_gtype(priv->client_factory, addr_family);
+ gtype = _client_factory_get_gtype(priv->client_factory, config->addr_family);
nm_log_trace(LOGD_DHCP,
"dhcp%c: creating IPv%c DHCP client of type %s",
- nm_utils_addr_family_to_char(addr_family),
- nm_utils_addr_family_to_char(addr_family),
+ nm_utils_addr_family_to_char(config->addr_family),
+ nm_utils_addr_family_to_char(config->addr_family),
g_type_name(gtype));
- client = g_object_new(gtype,
- NM_DHCP_CLIENT_MULTI_IDX,
- multi_idx,
- NM_DHCP_CLIENT_ADDR_FAMILY,
- addr_family,
- NM_DHCP_CLIENT_INTERFACE,
- iface,
- NM_DHCP_CLIENT_IFINDEX,
- ifindex,
- NM_DHCP_CLIENT_HWADDR,
- hwaddr,
- NM_DHCP_CLIENT_BROADCAST_HWADDR,
- bcast_hwaddr,
- NM_DHCP_CLIENT_UUID,
- uuid,
- NM_DHCP_CLIENT_IAID,
- (guint) iaid,
- NM_DHCP_CLIENT_IAID_EXPLICIT,
- iaid_explicit,
- NM_DHCP_CLIENT_HOSTNAME,
- hostname,
- NM_DHCP_CLIENT_MUD_URL,
- mud_url,
- NM_DHCP_CLIENT_ROUTE_TABLE,
- (guint) route_table,
- NM_DHCP_CLIENT_ROUTE_METRIC,
- (guint) route_metric,
- NM_DHCP_CLIENT_TIMEOUT,
- (guint) timeout,
- NM_DHCP_CLIENT_HOSTNAME_FLAGS,
- (guint) hostname_flags,
- NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER,
- vendor_class_identifier,
- NM_DHCP_CLIENT_REJECT_SERVERS,
- reject_servers,
- NM_DHCP_CLIENT_FLAGS,
- (guint) client_flags,
- NM_DHCP_CLIENT_ANYCAST_ADDRESS,
- anycast_address,
- NULL);
+ client = g_object_new(gtype, NM_DHCP_CLIENT_CONFIG, config, NULL);
/* unfortunately, our implementations work differently per address-family regarding client-id/DUID.
*
@@ -286,16 +202,10 @@ client_start(NMDhcpManager * self,
* default outside of NetworkManager API.
*/
- if (addr_family == AF_INET) {
- success = nm_dhcp_client_start_ip4(client, dhcp_client_id, last_ip4_address, error);
+ if (config->addr_family == AF_INET) {
+ success = nm_dhcp_client_start_ip4(client, error);
} else {
- success = nm_dhcp_client_start_ip6(client,
- dhcp_client_id,
- enforce_duid,
- ipv6_ll_addr,
- privacy,
- needed_prefixes,
- error);
+ success = nm_dhcp_client_start_ip6(client, error);
}
if (!success)
@@ -304,178 +214,6 @@ client_start(NMDhcpManager * self,
return g_steal_pointer(&client);
}
-/* Caller owns a reference to the NMDhcpClient on return */
-NMDhcpClient *
-nm_dhcp_manager_start_ip4(NMDhcpManager * self,
- NMDedupMultiIndex * multi_idx,
- const char * iface,
- int ifindex,
- GBytes * hwaddr,
- GBytes * bcast_hwaddr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- NMDhcpClientFlags client_flags,
- gboolean send_hostname,
- const char * dhcp_hostname,
- const char * dhcp_fqdn,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- GBytes * dhcp_client_id,
- guint32 timeout,
- const char * anycast_address,
- const char * last_ip_address,
- GBytes * vendor_class_identifier,
- const char *const * reject_servers,
- GError ** error)
-{
- NMDhcpManagerPrivate *priv;
- const char * hostname = NULL;
- gs_free char * hostname_tmp = NULL;
- gboolean use_fqdn = FALSE;
- char * dot;
-
- /* these flags are set automatically/prohibited, and not free to set to the caller. */
- nm_assert(!NM_FLAGS_ANY(client_flags,
- NM_DHCP_CLIENT_FLAGS_USE_FQDN | NM_DHCP_CLIENT_FLAGS_INFO_ONLY));
-
- g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL);
- priv = NM_DHCP_MANAGER_GET_PRIVATE(self);
-
- if (send_hostname) {
- /* Use, in order of preference:
- * 1. FQDN from configuration
- * 2. hostname from configuration
- * 3. system hostname (only host part)
- */
- if (dhcp_fqdn) {
- hostname = dhcp_fqdn;
- use_fqdn = TRUE;
- } else if (dhcp_hostname)
- hostname = dhcp_hostname;
- else {
- hostname = priv->default_hostname;
- if (hostname) {
- hostname_tmp = g_strdup(hostname);
- dot = strchr(hostname_tmp, '.');
- if (dot)
- *dot = '\0';
- hostname = hostname_tmp;
- }
- }
- }
-
- return client_start(
- self,
- AF_INET,
- multi_idx,
- iface,
- ifindex,
- hwaddr,
- bcast_hwaddr,
- uuid,
- route_table,
- route_metric,
- NULL,
- dhcp_client_id,
- FALSE,
- 0,
- FALSE,
- timeout,
- client_flags | (use_fqdn ? NM_DHCP_CLIENT_FLAGS_USE_FQDN : NM_DHCP_CLIENT_FLAGS_NONE),
- anycast_address,
- hostname,
- hostname_flags,
- mud_url,
- 0,
- last_ip_address,
- 0,
- vendor_class_identifier,
- reject_servers,
- error);
-}
-
-/* Caller owns a reference to the NMDhcpClient on return */
-NMDhcpClient *
-nm_dhcp_manager_start_ip6(NMDhcpManager * self,
- NMDedupMultiIndex * multi_idx,
- const char * iface,
- int ifindex,
- const struct in6_addr * ll_addr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- NMDhcpClientFlags client_flags,
- gboolean send_hostname,
- const char * dhcp_hostname,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- GBytes * duid,
- gboolean enforce_duid,
- guint32 iaid,
- gboolean iaid_explicit,
- guint32 timeout,
- const char * anycast_address,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error)
-{
- NMDhcpManagerPrivate *priv;
- const char * hostname = NULL;
-
- /* this flag is set automatically, and not free to set to the caller. */
- nm_assert(!NM_FLAGS_ANY(client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN));
-
- g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL);
- priv = NM_DHCP_MANAGER_GET_PRIVATE(self);
-
- if (send_hostname) {
- /* Always prefer the explicit dhcp-hostname if given */
- hostname = dhcp_hostname ?: priv->default_hostname;
- }
- return client_start(self,
- AF_INET6,
- multi_idx,
- iface,
- ifindex,
- NULL,
- NULL,
- uuid,
- route_table,
- route_metric,
- ll_addr,
- duid,
- enforce_duid,
- iaid,
- iaid_explicit,
- timeout,
- client_flags | NM_DHCP_CLIENT_FLAGS_USE_FQDN,
- anycast_address,
- hostname,
- hostname_flags,
- mud_url,
- privacy,
- NULL,
- needed_prefixes,
- NULL,
- NULL,
- error);
-}
-
-void
-nm_dhcp_manager_set_default_hostname(NMDhcpManager *manager, const char *hostname)
-{
- NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE(manager);
-
- nm_clear_g_free(&priv->default_hostname);
-
- /* Never send 'localhost'-type names to the DHCP server */
- if (!nm_utils_is_specific_hostname(hostname))
- return;
-
- priv->default_hostname = g_strdup(hostname);
-}
-
const char *
nm_dhcp_manager_get_config(NMDhcpManager *self)
{
@@ -573,20 +311,5 @@ nm_dhcp_manager_init(NMDhcpManager *self)
}
static void
-dispose(GObject *object)
-{
- NMDhcpManager * self = NM_DHCP_MANAGER(object);
- NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE(self);
-
- G_OBJECT_CLASS(nm_dhcp_manager_parent_class)->dispose(object);
-
- nm_clear_g_free(&priv->default_hostname);
-}
-
-static void
nm_dhcp_manager_class_init(NMDhcpManagerClass *manager_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(manager_class);
-
- object_class->dispose = dispose;
-}
+{}
diff --git a/src/core/dhcp/nm-dhcp-manager.h b/src/core/dhcp/nm-dhcp-manager.h
index ce160437a5..bbd68236a3 100644
--- a/src/core/dhcp/nm-dhcp-manager.h
+++ b/src/core/dhcp/nm-dhcp-manager.h
@@ -8,7 +8,6 @@
#define __NETWORKMANAGER_DHCP_MANAGER_H__
#include "nm-dhcp-client.h"
-#include "nm-ip4-config.h"
#include "nm-dhcp-config.h"
#define NM_TYPE_DHCP_MANAGER (nm_dhcp_manager_get_type())
@@ -32,51 +31,8 @@ const char *nm_dhcp_manager_get_config(NMDhcpManager *self);
void nm_dhcp_manager_set_default_hostname(NMDhcpManager *manager, const char *hostname);
-NMDhcpClient *nm_dhcp_manager_start_ip4(NMDhcpManager * manager,
- struct _NMDedupMultiIndex *multi_idx,
- const char * iface,
- int ifindex,
- GBytes * hwaddr,
- GBytes * bcast_hwaddr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- NMDhcpClientFlags client_flags,
- gboolean send_hostname,
- const char * dhcp_hostname,
- const char * dhcp_fqdn,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- GBytes * dhcp_client_id,
- guint32 timeout,
- const char * anycast_address,
- const char * last_ip_address,
- GBytes * vendor_class_identifier,
- const char *const * reject_servers,
- GError ** error);
-
-NMDhcpClient *nm_dhcp_manager_start_ip6(NMDhcpManager * manager,
- struct _NMDedupMultiIndex *multi_idx,
- const char * iface,
- int ifindex,
- const struct in6_addr * ll_addr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- NMDhcpClientFlags client_flags,
- gboolean send_hostname,
- const char * dhcp_hostname,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- GBytes * duid,
- gboolean enforce_duid,
- guint32 iaid,
- gboolean iaid_explicit,
- guint32 timeout,
- const char * anycast_address,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error);
+NMDhcpClient *
+nm_dhcp_manager_start_client(NMDhcpManager *manager, NMDhcpClientConfig *config, GError **error);
/* For testing only */
extern const char *nm_dhcp_helper_path;
diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c
index 56b485dd25..6ab7f8c18d 100644
--- a/src/core/dhcp/nm-dhcp-nettools.c
+++ b/src/core/dhcp/nm-dhcp-nettools.c
@@ -17,6 +17,7 @@
#include "libnm-std-aux/unaligned.h"
#include "libnm-glib-aux/nm-str-buf.h"
+#include "nm-l3-config-data.h"
#include "nm-utils.h"
#include "nm-config.h"
#include "nm-dhcp-utils.h"
@@ -151,7 +152,7 @@ lease_option_consume_route(const uint8_t **datap,
static gboolean
lease_parse_address(NDhcp4ClientLease *lease,
- NMIP4Config * ip4_config,
+ NML3ConfigData * l3cd,
GHashTable * options,
GError ** error)
{
@@ -256,23 +257,23 @@ lease_parse_address(NDhcp4ClientLease *lease,
a_next_server.s_addr);
}
- nm_ip4_config_add_address(ip4_config,
- &((const NMPlatformIP4Address){
- .address = a_address.s_addr,
- .peer_address = a_address.s_addr,
- .plen = a_plen,
- .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
- .timestamp = a_timestamp,
- .lifetime = a_lifetime,
- .preferred = a_lifetime,
- }));
+ nm_l3_config_data_add_address_4(l3cd,
+ &((const NMPlatformIP4Address){
+ .address = a_address.s_addr,
+ .peer_address = a_address.s_addr,
+ .plen = a_plen,
+ .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .timestamp = a_timestamp,
+ .lifetime = a_lifetime,
+ .preferred = a_lifetime,
+ }));
return TRUE;
}
static void
lease_parse_address_list(NDhcp4ClientLease * lease,
- NMIP4Config * ip4_config,
+ NML3ConfigData * l3cd,
NMDhcpOptionDhcp4Options option,
GHashTable * options,
NMStrBuf * sbuf)
@@ -304,13 +305,13 @@ lease_parse_address_list(NDhcp4ClientLease * lease,
* See https://github.com/systemd/systemd/issues/4524. */
continue;
}
- nm_ip4_config_add_nameserver(ip4_config, addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr);
break;
case NM_DHCP_OPTION_DHCP4_NIS_SERVERS:
- nm_ip4_config_add_nis_server(ip4_config, addr);
+ nm_l3_config_data_add_nis_server(l3cd, addr);
break;
case NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER:
- nm_ip4_config_add_wins(ip4_config, addr);
+ nm_l3_config_data_add_wins(l3cd, addr);
break;
case NM_DHCP_OPTION_DHCP4_NTP_SERVER:
break;
@@ -324,10 +325,8 @@ lease_parse_address_list(NDhcp4ClientLease * lease,
static void
lease_parse_routes(NDhcp4ClientLease *lease,
- NMIP4Config * ip4_config,
+ NML3ConfigData * l3cd,
GHashTable * options,
- guint32 route_table,
- guint32 route_metric,
NMStrBuf * sbuf)
{
char dest_str[NM_UTILS_INET_ADDRSTRLEN];
@@ -336,9 +335,9 @@ lease_parse_routes(NDhcp4ClientLease *lease,
in_addr_t gateway;
uint8_t plen;
guint32 m;
- gboolean has_router_from_classless = FALSE;
- gboolean has_classless = FALSE;
- guint32 default_route_metric = route_metric;
+ gboolean has_router_from_classless = FALSE;
+ gboolean has_classless = FALSE;
+ guint32 default_route_metric_offset = 0;
const guint8 *l_data;
gsize l_data_len;
int r;
@@ -367,26 +366,22 @@ lease_parse_routes(NDhcp4ClientLease *lease,
if (plen == 0) {
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
+ m = default_route_metric_offset++;
has_router_from_classless = TRUE;
- } else {
- m = route_metric;
- }
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .network = dest,
- .plen = plen,
- .gateway = gateway,
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .metric = m,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- }),
- NULL);
+ } else
+ m = 0;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .network = dest,
+ .plen = plen,
+ .gateway = gateway,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = m,
+ }));
}
has_classless = TRUE;
@@ -419,17 +414,17 @@ lease_parse_routes(NDhcp4ClientLease *lease,
continue;
}
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .network = dest,
- .plen = plen,
- .gateway = gateway,
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .metric = route_metric,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- }),
- NULL);
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .network = dest,
+ .plen = plen,
+ .gateway = gateway,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
+ }));
}
nm_dhcp_option_add_option(options,
@@ -463,19 +458,17 @@ lease_parse_routes(NDhcp4ClientLease *lease,
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .gateway = gateway,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = m,
- }),
- NULL);
+ m = default_route_metric_offset++;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = gateway,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = m,
+ }));
}
nm_dhcp_option_add_option(options,
@@ -486,7 +479,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
}
static void
-lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options)
+lease_parse_search_domains(NDhcp4ClientLease *lease, NML3ConfigData *l3cd, GHashTable *options)
{
gs_strfreev char **domains = NULL;
const guint8 * l_data;
@@ -504,7 +497,7 @@ lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GH
return;
for (i = 0; domains[i]; i++)
- nm_ip4_config_add_search(ip4_config, domains[i]);
+ nm_l3_config_data_add_search(l3cd, AF_INET, domains[i]);
nm_dhcp_option_take_option(options,
AF_INET,
@@ -539,34 +532,31 @@ lease_parse_private_options(NDhcp4ClientLease *lease, GHashTable *options)
}
}
-static NMIP4Config *
+static NML3ConfigData *
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
const char * iface,
int ifindex,
NDhcp4ClientLease *lease,
- guint32 route_table,
- guint32 route_metric,
- GHashTable ** out_options,
GError ** error)
{
- nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE);
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
const guint8 * l_data;
gsize l_data_len;
const char * v_str;
guint16 v_u16;
- gboolean v_bool;
in_addr_t v_inaddr;
struct in_addr v_inaddr_s;
int r;
g_return_val_if_fail(lease != NULL, NULL);
- ip4_config = nm_ip4_config_new(multi_idx, ifindex);
- options = nm_dhcp_option_create_options_dict();
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
+
+ options = nm_dhcp_option_create_options_dict();
- if (!lease_parse_address(lease, ip4_config, options, error))
+ if (!lease_parse_address(lease, l3cd, options, error))
return NULL;
r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s);
@@ -585,13 +575,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
v_inaddr);
}
- lease_parse_routes(lease, ip4_config, options, route_table, route_metric, &sbuf);
+ lease_parse_routes(lease, l3cd, options, &sbuf);
- lease_parse_address_list(lease,
- ip4_config,
- NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
- options,
- &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, options, &sbuf);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
@@ -616,7 +602,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_str_buf_append_required_delimiter(&sbuf, ' ');
nm_str_buf_append(&sbuf, s);
- nm_ip4_config_add_domain(ip4_config, s);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, s);
}
}
@@ -628,18 +614,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
}
}
- lease_parse_search_domains(lease, ip4_config, options);
+ lease_parse_search_domains(lease, l3cd, options);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_mtu(l_data, l_data_len, &v_u16)) {
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, v_u16);
- nm_ip4_config_set_mtu(ip4_config, v_u16, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_set_mtu(l3cd, v_u16);
}
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, &l_data, &l_data_len);
- v_bool =
- (r == 0) && memmem(l_data, l_data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED"));
- nm_ip4_config_set_metered(ip4_config, v_bool);
+ if ((r == 0) && memmem(l_data, l_data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
+ nm_l3_config_data_set_metered(l3cd, TRUE);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_HOST_NAME, &l_data, &l_data_len);
if (r == 0) {
@@ -650,7 +635,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
}
}
- lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROOT_PATH, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
@@ -681,11 +666,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* We reject NUL characters inside the string (except trailing NULs).
* Otherwise, we allow any encoding and backslash-escape the result to
* UTF-8. */
- nm_dhcp_option_add_option_utf8safe_escape(options,
- AF_INET,
- NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
- l_data,
- l_data_len);
+ gs_free char *to_free = NULL;
+ const char * escaped;
+
+ escaped = nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
+ nm_dhcp_option_add_option(options,
+ AF_INET,
+ NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
+ escaped ?: "");
+
+ nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
+ nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
}
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, &l_data, &l_data_len);
@@ -700,7 +691,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
&to_free);
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, v_str ?: "");
- nm_ip4_config_set_nis_domain(ip4_config, v_str ?: "");
+ nm_l3_config_data_set_nis_domain(l3cd, v_str ?: "");
}
r = n_dhcp4_client_lease_get_file(lease, &v_str);
@@ -728,18 +719,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
v_str ?: "");
}
- lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
- lease_parse_address_list(lease,
- ip4_config,
- NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER,
- options,
- &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, options, &sbuf);
lease_parse_private_options(lease, options);
- NM_SET_OUT(out_options, g_steal_pointer(&options));
- return g_steal_pointer(&ip4_config);
+ nm_dhcp_option_add_requests_to_options(options, AF_INET);
+
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
+
+ return g_steal_pointer(&l3cd);
}
/*****************************************************************************/
@@ -771,47 +761,44 @@ lease_save(NMDhcpNettools *self, NDhcp4ClientLease *lease, const char *lease_fil
static void
bound4_handle(NMDhcpNettools *self, NDhcp4ClientLease *lease, gboolean extended)
{
- NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
- const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
- GError * error = NULL;
+ NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
+ NMDhcpClient * client = NM_DHCP_CLIENT(self);
+ const NMDhcpClientConfig *client_config;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ GError * error = NULL;
_LOGT("lease available (%s)", extended ? "extended" : "new");
-
- ip4_config = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
- iface,
- nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
- lease,
- nm_dhcp_client_get_route_table(NM_DHCP_CLIENT(self)),
- nm_dhcp_client_get_route_metric(NM_DHCP_CLIENT(self)),
- &options,
- &error);
- if (!ip4_config) {
- _LOGW("%s", error->message);
+ client_config = nm_dhcp_client_get_config(client);
+ l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(client),
+ client_config->iface,
+ nm_dhcp_client_get_ifindex(client),
+ lease,
+ &error);
+ if (!l3cd) {
+ _LOGW("failure to parse lease: %s", error->message);
g_clear_error(&error);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
- nm_dhcp_option_add_requests_to_options(options, AF_INET);
lease_save(self, lease, priv->lease_file);
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
- NM_IP_CONFIG_CAST(ip4_config),
- options);
+ l3cd);
}
static void
dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
{
- NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
- struct in_addr server_id;
- char addr_str[INET_ADDRSTRLEN];
- int r;
+ NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
+ const NMDhcpClientConfig *client_config;
+ struct in_addr server_id;
+ char addr_str[INET_ADDRSTRLEN];
+ int r;
_LOGT("client event %d", event->event);
+ client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self));
switch (event->event) {
case N_DHCP4_CLIENT_EVENT_OFFER:
@@ -835,10 +822,10 @@ dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
break;
case N_DHCP4_CLIENT_EVENT_RETRACTED:
case N_DHCP4_CLIENT_EVENT_EXPIRED:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_EXPIRE, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_EXPIRE, NULL);
break;
case N_DHCP4_CLIENT_EVENT_CANCELLED:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
break;
case N_DHCP4_CLIENT_EVENT_GRANTED:
priv->lease = n_dhcp4_client_lease_ref(event->granted.lease);
@@ -861,7 +848,7 @@ dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
NULL,
NULL,
"dhcp4 (%s): %s",
- nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self)),
+ client_config->iface,
event->log.message);
}
} break;
@@ -890,13 +877,12 @@ dhcp4_event_cb(int fd, GIOCondition condition, gpointer user_data)
*/
_LOGE("error %d dispatching events", r);
nm_clear_g_source_inst(&priv->event_source);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return G_SOURCE_REMOVE;
}
- while (!n_dhcp4_client_pop_event(priv->client, &event) && event) {
+ while (!n_dhcp4_client_pop_event(priv->client, &event) && event)
dhcp4_event_handle(self, event);
- }
return G_SOURCE_CONTINUE;
}
@@ -914,23 +900,26 @@ nettools_create(NMDhcpNettools *self, GError **error)
gsize hwaddr_len;
gsize bcast_hwaddr_len;
GBytes * client_id;
- gs_unref_bytes GBytes *client_id_new = NULL;
- const uint8_t * client_id_arr;
- size_t client_id_len;
- int r, fd, arp_type, transport;
+ gs_unref_bytes GBytes * client_id_new = NULL;
+ const uint8_t * client_id_arr;
+ size_t client_id_len;
+ int r, fd, arp_type, transport;
+ const NMDhcpClientConfig *client_config;
+
+ client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self));
g_return_val_if_fail(!priv->client, FALSE);
/* TODO: honor nm_dhcp_client_get_anycast_address() */
- hwaddr = nm_dhcp_client_get_hw_addr(NM_DHCP_CLIENT(self));
+ hwaddr = client_config->hwaddr;
if (!hwaddr || !(hwaddr_arr = g_bytes_get_data(hwaddr, &hwaddr_len))
|| (arp_type = nm_utils_arp_type_detect_from_hwaddrlen(hwaddr_len)) < 0) {
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
return FALSE;
}
- bcast_hwaddr = nm_dhcp_client_get_broadcast_hw_addr(NM_DHCP_CLIENT(self));
+ bcast_hwaddr = client_config->bcast_hwaddr;
bcast_hwaddr_arr = g_bytes_get_data(bcast_hwaddr, &bcast_hwaddr_len);
switch (arp_type) {
@@ -947,7 +936,7 @@ nettools_create(NMDhcpNettools *self, GError **error)
/* Note that we always set a client-id. In particular for infiniband that is necessary,
* see https://tools.ietf.org/html/rfc4390#section-2.1 . */
- client_id = nm_dhcp_client_get_client_id(NM_DHCP_CLIENT(self));
+ client_id = client_config->client_id;
if (!client_id) {
client_id_new = nm_utils_dhcp_client_id_mac(arp_type, hwaddr_arr, hwaddr_len);
client_id = client_id_new;
@@ -971,10 +960,7 @@ nettools_create(NMDhcpNettools *self, GError **error)
n_dhcp4_client_config_set_transport(config, transport);
n_dhcp4_client_config_set_mac(config, hwaddr_arr, hwaddr_len);
n_dhcp4_client_config_set_broadcast_mac(config, bcast_hwaddr_arr, bcast_hwaddr_len);
- n_dhcp4_client_config_set_request_broadcast(
- config,
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
- NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST));
+ n_dhcp4_client_config_set_request_broadcast(config, client_config->v4.request_broadcast);
r = n_dhcp4_client_config_set_client_id(config,
client_id_arr,
NM_MIN(client_id_len, 1 + _NM_MAX_CLIENT_ID_LEN));
@@ -1033,7 +1019,7 @@ decline(NMDhcpClient *client, const char *error_message, GError **error)
g_return_val_if_fail(priv->lease, FALSE);
- _LOGT("dhcp4-client: decline");
+ _LOGT("dhcp4-client: decline (%s)", error_message);
r = n_dhcp4_client_lease_decline(priv->lease, error_message);
if (r) {
@@ -1063,19 +1049,20 @@ fqdn_flags_to_wire(NMDhcpHostnameFlags flags)
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
nm_auto(n_dhcp4_client_probe_config_freep) NDhcp4ClientProbeConfig *config = NULL;
- NMDhcpNettools * self = NM_DHCP_NETTOOLS(client);
- NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
- gs_free char * lease_file = NULL;
- struct in_addr last_addr = {0};
- const char * hostname;
- const char * mud_url;
- GBytes * vendor_class_identifier;
- int r, i;
+ NMDhcpNettools * self = NM_DHCP_NETTOOLS(client);
+ NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
+ const NMDhcpClientConfig *client_config;
+ gs_free char * lease_file = NULL;
+ struct in_addr last_addr = {0};
+ int r, i;
+
+ client_config = nm_dhcp_client_get_config(client);
g_return_val_if_fail(!priv->probe, FALSE);
+ g_return_val_if_fail(client_config, FALSE);
if (!nettools_create(self, error))
return FALSE;
@@ -1094,12 +1081,12 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
nm_dhcp_utils_get_leasefile_path(AF_INET,
"internal",
- nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
+ client_config->iface,
+ client_config->uuid,
&lease_file);
- if (last_ip4_address)
- inet_pton(AF_INET, last_ip4_address, &last_addr);
+ if (client_config->v4.last_address)
+ inet_pton(AF_INET, client_config->v4.last_address, &last_addr);
else {
/*
* TODO: we stick to the systemd-networkd lease file format. Quite easy for now to
@@ -1129,31 +1116,33 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- mud_url = nm_dhcp_client_get_mud_url(client);
- if (mud_url) {
+ if (client_config->mud_url) {
r = n_dhcp4_client_probe_config_append_option(config,
NM_DHCP_OPTION_DHCP4_MUD_URL,
- mud_url,
- strlen(mud_url));
+ client_config->mud_url,
+ strlen(client_config->mud_url));
if (r) {
set_error_nettools(error, r, "failed to set MUD URL");
return FALSE;
}
}
- hostname = nm_dhcp_client_get_hostname(client);
- if (hostname) {
- if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN)) {
+
+ if (client_config->hostname) {
+ if (client_config->use_fqdn) {
uint8_t buffer[255];
NMDhcpHostnameFlags flags;
size_t fqdn_len;
- flags = nm_dhcp_client_get_hostname_flags(client);
+ flags = client_config->hostname_flags;
buffer[0] = fqdn_flags_to_wire(flags);
buffer[1] = 0; /* RCODE1 (deprecated) */
buffer[2] = 0; /* RCODE2 (deprecated) */
if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) {
- r = nm_sd_dns_name_to_wire_format(hostname, buffer + 3, sizeof(buffer) - 3, FALSE);
+ r = nm_sd_dns_name_to_wire_format(client_config->hostname,
+ buffer + 3,
+ sizeof(buffer) - 3,
+ FALSE);
if (r <= 0) {
if (r < 0)
nm_utils_error_set_errno(error, r, "failed to convert DHCP FQDN: %s");
@@ -1163,12 +1152,12 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
fqdn_len = r;
} else {
- fqdn_len = strlen(hostname);
+ fqdn_len = strlen(client_config->hostname);
if (fqdn_len > sizeof(buffer) - 3) {
nm_utils_error_set(error, r, "failed to set DHCP FQDN: name too long");
return FALSE;
}
- memcpy(buffer + 3, hostname, fqdn_len);
+ memcpy(buffer + 3, client_config->hostname, fqdn_len);
}
r = n_dhcp4_client_probe_config_append_option(config,
@@ -1182,8 +1171,8 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
} else {
r = n_dhcp4_client_probe_config_append_option(config,
NM_DHCP_OPTION_DHCP4_HOST_NAME,
- hostname,
- strlen(hostname));
+ client_config->hostname,
+ strlen(client_config->hostname));
if (r) {
set_error_nettools(error, r, "failed to set DHCP hostname");
return FALSE;
@@ -1191,12 +1180,11 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- vendor_class_identifier = nm_dhcp_client_get_vendor_class_identifier(client);
- if (vendor_class_identifier) {
+ if (client_config->vendor_class_identifier) {
const void *option_data;
gsize option_size;
- option_data = g_bytes_get_data(vendor_class_identifier, &option_size);
+ option_data = g_bytes_get_data(client_config->vendor_class_identifier, &option_size);
nm_assert(option_data);
nm_assert(option_size <= 255);
diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c
index af1d2238b4..a6adc0ccdc 100644
--- a/src/core/dhcp/nm-dhcp-systemd.c
+++ b/src/core/dhcp/nm-dhcp-systemd.c
@@ -17,6 +17,7 @@
#include "libnm-std-aux/unaligned.h"
#include "nm-utils.h"
+#include "nm-l3-config-data.h"
#include "nm-dhcp-utils.h"
#include "nm-dhcp-options.h"
#include "nm-core-utils.h"
@@ -51,8 +52,6 @@ typedef struct {
char * lease_file;
guint request_count;
-
- bool privacy : 1;
} NMDhcpSystemdPrivate;
struct _NMDhcpSystemd {
@@ -70,18 +69,15 @@ G_DEFINE_TYPE(NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT)
/*****************************************************************************/
-static NMIP4Config *
+static NML3ConfigData *
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
const char * iface,
int ifindex,
sd_dhcp_lease * lease,
- guint32 route_table,
- guint32 route_metric,
- GHashTable ** out_options,
GError ** error)
{
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
const struct in_addr * addr_list;
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
const char * s;
@@ -92,7 +88,6 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
int i, num;
const void * data;
gsize data_len;
- gboolean metered = FALSE;
gboolean has_router_from_classless = FALSE;
gboolean has_classless_route = FALSE;
gboolean has_static_route = FALSE;
@@ -133,9 +128,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
return NULL;
}
- ip4_config = nm_ip4_config_new(multi_idx, ifindex);
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
- options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
+ options = nm_dhcp_option_create_options_dict();
_nm_utils_inet4_ntop(a_address.s_addr, addr_str);
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str);
@@ -160,16 +155,16 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, addr_str);
}
- nm_ip4_config_add_address(ip4_config,
- &((const NMPlatformIP4Address){
- .address = a_address.s_addr,
- .peer_address = a_address.s_addr,
- .plen = a_plen,
- .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
- .timestamp = ts,
- .lifetime = a_lifetime,
- .preferred = a_lifetime,
- }));
+ nm_l3_config_data_add_address_4(l3cd,
+ &((const NMPlatformIP4Address){
+ .address = a_address.s_addr,
+ .peer_address = a_address.s_addr,
+ .plen = a_plen,
+ .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .timestamp = ts,
+ .lifetime = a_lifetime,
+ .preferred = a_lifetime,
+ }));
if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) {
_nm_utils_inet4_ntop(server_id.s_addr, addr_str);
@@ -193,7 +188,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* See https://github.com/systemd/systemd/issues/4524. */
continue;
}
- nm_ip4_config_add_nameserver(ip4_config, addr_list[i].s_addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr_list[i].s_addr);
}
nm_dhcp_option_add_option(options,
AF_INET,
@@ -206,7 +201,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_gstring_prepare(&str);
for (i = 0; i < num; i++) {
g_string_append(nm_gstring_add_space_delimiter(str), search_domains[i]);
- nm_ip4_config_add_search(ip4_config, search_domains[i]);
+ nm_l3_config_data_add_search(l3cd, AF_INET, search_domains[i]);
}
nm_dhcp_option_add_option(options,
AF_INET,
@@ -224,7 +219,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* As systemd escapes such characters, split them at \\032. */
domains = g_strsplit(s, "\\032", 0);
for (d = domains; *d; d++)
- nm_ip4_config_add_domain(ip4_config, *d);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, *d);
}
if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) {
@@ -233,9 +228,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
num = sd_dhcp_lease_get_routes(lease, &routes);
if (num > 0) {
- nm_auto_free_gstring GString *str_classless = NULL;
- nm_auto_free_gstring GString *str_static = NULL;
- guint32 default_route_metric = route_metric;
+ nm_auto_free_gstring GString *str_classless = NULL;
+ nm_auto_free_gstring GString *str_static = NULL;
+ guint32 default_route_metric_offset = 0;
for (i = 0; i < num; i++) {
switch (sd_dhcp_route_get_option(routes[i])) {
@@ -307,25 +302,22 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
if (r_plen == 0) {
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
+ m = default_route_metric_offset++;
has_router_from_classless = TRUE;
} else
- m = route_metric;
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .network = network_net,
- .plen = r_plen,
- .gateway = r_gateway.s_addr,
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .metric = m,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- }),
- NULL);
+ m = 0;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .network = network_net,
+ .plen = r_plen,
+ .gateway = r_gateway.s_addr,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .metric_any = TRUE,
+ .metric = m,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ }));
}
if (str_classless && str_classless->len > 0)
@@ -342,7 +334,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
num = sd_dhcp_lease_get_router(lease, &a_router);
if (num > 0) {
- guint32 default_route_metric = route_metric;
+ guint32 default_route_metric_offset = 0;
nm_gstring_prepare(&str);
for (i = 0; i < num; i++) {
@@ -368,26 +360,24 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .gateway = a_router[i].s_addr,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = m,
- }),
- NULL);
+ m = default_route_metric_offset++;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = a_router[i].s_addr,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = m,
+ }));
}
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROUTER, str->str);
}
if (sd_dhcp_lease_get_mtu(lease, &mtu) >= 0 && mtu) {
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, mtu);
- nm_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_set_mtu(l3cd, mtu);
}
num = sd_dhcp_lease_get_ntp(lease, &addr_list);
@@ -422,9 +412,10 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, s);
}
- if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0)
- metered = !!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED"));
- nm_ip4_config_set_metered(ip4_config, metered);
+ if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0) {
+ if (!!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
+ nm_l3_config_data_set_metered(l3cd, TRUE);
+ }
num = nm_sd_dhcp_lease_get_private_options(lease, &private_options);
if (num > 0) {
@@ -436,12 +427,18 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY) {
if (nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
- nm_dhcp_option_add_option_utf8safe_escape(
- options,
- AF_INET,
- NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
- l_data,
- l_data_len);
+ gs_free char *to_free = NULL;
+ const char * escaped;
+
+ escaped =
+ nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
+ nm_dhcp_option_add_option(options,
+ AF_INET,
+ NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
+ escaped ?: "");
+
+ nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
+ nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
}
continue;
}
@@ -458,8 +455,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_take_option(options, AF_INET, code, option_string);
}
}
- NM_SET_OUT(out_options, g_steal_pointer(&options));
- return g_steal_pointer(&ip4_config);
+
+ nm_dhcp_option_add_requests_to_options(options, AF_INET);
+
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
+
+ return g_steal_pointer(&l3cd);
}
/*****************************************************************************/
@@ -467,43 +468,38 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
static void
bound4_handle(NMDhcpSystemd *self, gboolean extended)
{
- NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
- const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
- sd_dhcp_lease * lease = NULL;
- GError * error = NULL;
+ NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
+ sd_dhcp_lease * lease = NULL;
+ GError * error = NULL;
if (sd_dhcp_client_get_lease(priv->client4, &lease) < 0 || !lease) {
_LOGW("no lease!");
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
_LOGD("lease available");
- ip4_config = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
- iface,
- nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
- lease,
- nm_dhcp_client_get_route_table(NM_DHCP_CLIENT(self)),
- nm_dhcp_client_get_route_metric(NM_DHCP_CLIENT(self)),
- &options,
- &error);
- if (!ip4_config) {
+ l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
+ iface,
+ nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
+ lease,
+ &error);
+ if (!l3cd) {
_LOGW("%s", error->message);
g_clear_error(&error);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
- nm_dhcp_option_add_requests_to_options(options, AF_INET);
dhcp_lease_save(lease, priv->lease_file);
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
- NM_IP_CONFIG_CAST(ip4_config),
- options);
+ l3cd);
}
static int
@@ -522,10 +518,10 @@ dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data)
switch (event) {
case SD_DHCP_CLIENT_EVENT_EXPIRED:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL);
break;
case SD_DHCP_CLIENT_EVENT_STOP:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL);
break;
case SD_DHCP_CLIENT_EVENT_RENEW:
case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
@@ -558,11 +554,12 @@ dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data)
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
- nm_auto(sd_dhcp_client_unrefp) sd_dhcp_client *sd_client = NULL;
- NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client);
- NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ nm_auto(sd_dhcp_client_unrefp) sd_dhcp_client *sd_client = NULL;
+ NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client);
+ NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ const NMDhcpClientConfig * client_config;
gs_free char * lease_file = NULL;
GBytes * hwaddr;
const uint8_t * hwaddr_arr;
@@ -584,6 +581,8 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
g_return_val_if_fail(!priv->client4, FALSE);
g_return_val_if_fail(!priv->client6, FALSE);
+ client_config = nm_dhcp_client_get_config(client);
+
/* TODO: honor nm_dhcp_client_get_anycast_address() */
r = sd_dhcp_client_new(&sd_client, FALSE);
@@ -600,7 +599,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
return FALSE;
}
- hwaddr = nm_dhcp_client_get_hw_addr(client);
+ hwaddr = client_config->hwaddr;
if (!hwaddr || !(hwaddr_arr = g_bytes_get_data(hwaddr, &hwaddr_len))
|| (arp_type = nm_utils_arp_type_detect_from_hwaddrlen(hwaddr_len)) < 0) {
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
@@ -608,7 +607,8 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
bcast_hwaddr_arr = NULL;
- if ((bcast_hwaddr = nm_dhcp_client_get_broadcast_hw_addr(NM_DHCP_CLIENT(self)))) {
+ bcast_hwaddr = client_config->bcast_hwaddr;
+ if (bcast_hwaddr) {
bcast_hwaddr_arr = g_bytes_get_data(bcast_hwaddr, &bcast_hwaddr_len);
if (bcast_hwaddr_len != hwaddr_len)
bcast_hwaddr_arr = NULL;
@@ -632,12 +632,12 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
nm_dhcp_utils_get_leasefile_path(AF_INET,
"internal",
- nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
+ client_config->iface,
+ client_config->uuid,
&lease_file);
- if (last_ip4_address)
- inet_pton(AF_INET, last_ip4_address, &last_addr);
+ if (client_config->v4.last_address)
+ inet_pton(AF_INET, client_config->v4.last_address, &last_addr);
else {
nm_auto(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
@@ -646,9 +646,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
sd_dhcp_lease_get_address(lease, &last_addr);
}
- r = sd_dhcp_client_set_request_broadcast(sd_client,
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client),
- NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST));
+ r = sd_dhcp_client_set_request_broadcast(sd_client, client_config->v4.request_broadcast);
nm_assert(r >= 0);
if (last_addr.s_addr) {
@@ -659,7 +657,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- client_id = nm_dhcp_client_get_client_id(client);
+ client_id = client_config->client_id;
if (!client_id) {
client_id_new = nm_utils_dhcp_client_id_mac(arp_type, hwaddr_arr, hwaddr_len);
client_id = client_id_new;
@@ -694,7 +692,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- hostname = nm_dhcp_client_get_hostname(client);
+ hostname = client_config->hostname;
if (hostname) {
/* FIXME: sd-dhcp decides which hostname/FQDN option to send (12 or 81)
* only based on whether the hostname has a domain part or not. At the
@@ -707,7 +705,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- mud_url = nm_dhcp_client_get_mud_url(client);
+ mud_url = client_config->mud_url;
if (mud_url) {
r = sd_dhcp_client_set_mud_url(sd_client, mud_url);
if (r < 0) {
@@ -716,7 +714,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- vendor_class_identifier = nm_dhcp_client_get_vendor_class_identifier(client);
+ vendor_class_identifier = client_config->vendor_class_identifier;
if (vendor_class_identifier) {
const char *option_data;
gsize len;
@@ -745,7 +743,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
g_free(priv->lease_file);
priv->lease_file = g_steal_pointer(&lease_file);
- nm_dhcp_client_set_client_id(client, client_id);
+ nm_dhcp_client_set_effective_client_id(client, client_id);
r = sd_dhcp_client_start(priv->client4);
if (r < 0) {
@@ -759,32 +757,32 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
return TRUE;
}
-static NMIP6Config *
+static NML3ConfigData *
lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
const char * iface,
int ifindex,
sd_dhcp6_lease * lease,
gboolean info_only,
- GHashTable ** out_options,
gint32 ts,
GError ** error)
{
- gs_unref_object NMIP6Config *ip6_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
struct in6_addr tmp_addr;
const struct in6_addr * dns;
uint32_t lft_pref, lft_valid;
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
char ** domains;
const char * s;
- nm_auto_free_gstring GString *str = NULL;
+ nm_auto_free_gstring GString *str = NULL;
+ gboolean has_any_addresses = FALSE;
int num, i;
nm_assert(lease);
- ip6_config = nm_ip6_config_new(multi_idx, ifindex);
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
- options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
+ options = nm_dhcp_option_create_options_dict();
sd_dhcp6_lease_reset_address_iter(lease);
nm_gstring_prepare(&str);
@@ -798,15 +796,19 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
};
- nm_ip6_config_add_address(ip6_config, &address);
+ nm_l3_config_data_add_address_6(l3cd, &address);
_nm_utils_inet6_ntop(&tmp_addr, addr_str);
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
- };
- if (str->len)
+
+ has_any_addresses = TRUE;
+ }
+
+ if (str->len) {
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, str->str);
+ }
- if (!info_only && nm_ip6_config_get_num_addresses(ip6_config) == 0) {
+ if (!info_only && !has_any_addresses) {
g_set_error_literal(error,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_FAILED,
@@ -820,7 +822,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
for (i = 0; i < num; i++) {
_nm_utils_inet6_ntop(&dns[i], addr_str);
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
- nm_ip6_config_add_nameserver(ip6_config, &dns[i]);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &dns[i]);
}
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DNS_SERVERS, str->str);
}
@@ -830,7 +832,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
nm_gstring_prepare(&str);
for (i = 0; i < num; i++) {
g_string_append(nm_gstring_add_space_delimiter(str), domains[i]);
- nm_ip6_config_add_search(ip6_config, domains[i]);
+ nm_l3_config_data_add_search(l3cd, AF_INET6, domains[i]);
}
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, str->str);
}
@@ -839,51 +841,48 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_FQDN, s);
}
- NM_SET_OUT(out_options, g_steal_pointer(&options));
- return g_steal_pointer(&ip6_config);
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET6, g_steal_pointer(&options));
+
+ return g_steal_pointer(&l3cd);
}
static void
bound6_handle(NMDhcpSystemd *self)
{
- NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
- const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
- const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
- gs_unref_object NMIP6Config *ip6_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
- gs_free_error GError *error = NULL;
- NMPlatformIP6Address prefix = {0};
- sd_dhcp6_lease * lease = NULL;
+ NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
+ const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
+ const NMDhcpClientConfig *client_config;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_free_error GError *error = NULL;
+ NMPlatformIP6Address prefix = {0};
+ sd_dhcp6_lease * lease = NULL;
+
+ client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self));
if (sd_dhcp6_client_get_lease(priv->client6, &lease) < 0 || !lease) {
_LOGW(" no lease!");
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
_LOGD("lease available");
- ip6_config =
- lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
- iface,
- nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
- lease,
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
- NM_DHCP_CLIENT_FLAGS_INFO_ONLY),
- &options,
- ts,
- &error);
-
- if (!ip6_config) {
+ l3cd = lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
+ iface,
+ nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
+ lease,
+ client_config->v6.info_only,
+ ts,
+ &error);
+
+ if (!l3cd) {
_LOGW("%s", error->message);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
- NM_DHCP_STATE_BOUND,
- NM_IP_CONFIG_CAST(ip6_config),
- options);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_BOUND, l3cd);
sd_dhcp6_lease_reset_pd_prefix_iter(lease);
while (!sd_dhcp6_lease_get_pd(lease,
@@ -908,11 +907,11 @@ dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data)
switch (event) {
case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_TIMEOUT, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_TIMEOUT, NULL);
break;
case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE:
case SD_DHCP6_CLIENT_EVENT_STOP:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL);
break;
case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE:
case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST:
@@ -925,15 +924,12 @@ dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data)
}
static gboolean
-ip6_start(NMDhcpClient * client,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error)
+ip6_start(NMDhcpClient *client, GError **error)
{
NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client);
NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
nm_auto(sd_dhcp6_client_unrefp) sd_dhcp6_client *sd_client = NULL;
+ const NMDhcpClientConfig * client_config;
const char * hostname;
const char * mud_url;
int r, i;
@@ -944,10 +940,12 @@ ip6_start(NMDhcpClient * client,
g_return_val_if_fail(!priv->client4, FALSE);
g_return_val_if_fail(!priv->client6, FALSE);
+ client_config = nm_dhcp_client_get_config(client);
+
/* TODO: honor nm_dhcp_client_get_anycast_address() */
- if (!(duid = nm_dhcp_client_get_client_id(client))
- || !(duid_arr = g_bytes_get_data(duid, &duid_len)) || duid_len < 2) {
+ duid = nm_dhcp_client_get_effective_client_id(client);
+ if (!duid || !(duid_arr = g_bytes_get_data(duid, &duid_len)) || duid_len < 2) {
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "missing DUID");
g_return_val_if_reached(FALSE);
}
@@ -960,13 +958,13 @@ ip6_start(NMDhcpClient * client,
_LOGT("dhcp-client6: set %p", sd_client);
- if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_INFO_ONLY)) {
+ if (client_config->v6.info_only) {
sd_dhcp6_client_set_address_request(sd_client, 0);
- if (needed_prefixes == 0)
+ if (client_config->v6.needed_prefixes == 0)
sd_dhcp6_client_set_information_request(sd_client, 1);
}
- r = sd_dhcp6_client_set_iaid(sd_client, nm_dhcp_client_get_iaid(client));
+ r = sd_dhcp6_client_set_iaid(sd_client, client_config->v6.iaid);
if (r < 0) {
nm_utils_error_set_errno(error, r, "failed to set IAID: %s");
return FALSE;
@@ -1002,7 +1000,7 @@ ip6_start(NMDhcpClient * client,
}
}
- mud_url = nm_dhcp_client_get_mud_url(client);
+ mud_url = client_config->mud_url;
if (mud_url) {
r = sd_dhcp6_client_set_request_mud_url(sd_client, mud_url);
if (r < 0) {
@@ -1011,8 +1009,8 @@ ip6_start(NMDhcpClient * client,
}
}
- if (needed_prefixes > 0) {
- if (needed_prefixes > 1)
+ if (client_config->v6.needed_prefixes > 0) {
+ if (client_config->v6.needed_prefixes > 1)
_LOGW("dhcp-client6: only one prefix request is supported");
/* FIXME: systemd-networkd API only allows to request a
* single prefix */
@@ -1023,13 +1021,13 @@ ip6_start(NMDhcpClient * client,
}
}
- r = sd_dhcp6_client_set_local_address(sd_client, ll_addr);
+ r = sd_dhcp6_client_set_local_address(sd_client, client_config->v6.ll_addr);
if (r < 0) {
nm_utils_error_set_errno(error, r, "failed to set local address: %s");
return FALSE;
}
- hostname = nm_dhcp_client_get_hostname(client);
+ hostname = client_config->hostname;
r = sd_dhcp6_client_set_fqdn(sd_client, hostname);
if (r < 0) {
nm_utils_error_set_errno(error, r, "failed to set DHCP hostname: %s");
diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c
index 3cc6987ada..b1ff1b97a9 100644
--- a/src/core/dhcp/nm-dhcp-utils.c
+++ b/src/core/dhcp/nm-dhcp-utils.c
@@ -14,6 +14,7 @@
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
#include "nm-dhcp-utils.h"
+#include "nm-l3-config-data.h"
#include "nm-utils.h"
#include "nm-config.h"
#include "NetworkManagerUtils.h"
@@ -24,12 +25,10 @@
/*****************************************************************************/
static gboolean
-ip4_process_dhcpcd_rfc3442_routes(const char * iface,
- const char * str,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config,
- guint32 * gwaddr)
+ip4_process_dhcpcd_rfc3442_routes(const char * iface,
+ const char * str,
+ NML3ConfigData *l3cd,
+ guint32 * gwaddr)
{
gs_free const char **routes = NULL;
const char ** r;
@@ -45,10 +44,9 @@ ip4_process_dhcpcd_rfc3442_routes(const char * iface,
}
for (r = routes; *r; r += 2) {
- char * slash;
- NMPlatformIP4Route route;
- int rt_cidr = 32;
- guint32 rt_addr, rt_route;
+ char * slash;
+ int rt_cidr = 32;
+ guint32 rt_addr, rt_route;
slash = strchr(*r, '/');
if (slash) {
@@ -89,14 +87,18 @@ ip4_process_dhcpcd_rfc3442_routes(const char * iface,
*r,
rt_cidr,
*(r + 1));
- memset(&route, 0, sizeof(route));
- route.network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr);
- route.plen = rt_cidr;
- route.gateway = rt_route;
- route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
- route.metric = route_metric;
- route.table_coerced = nm_platform_route_table_coerce(route_table);
- nm_ip4_config_add_route(ip4_config, &route, NULL);
+
+ nm_l3_config_data_add_route_4(
+ l3cd,
+ &((const NMPlatformIP4Route){
+ .network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr),
+ .plen = rt_cidr,
+ .gateway = rt_route,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .metric_any = TRUE,
+ .table_any = TRUE,
+
+ }));
}
}
@@ -153,12 +155,10 @@ process_dhclient_rfc3442_route(const char *const **p_octets, NMPlatformIP4Route
}
static gboolean
-ip4_process_dhclient_rfc3442_routes(const char * iface,
- const char * str,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config,
- guint32 * gwaddr)
+ip4_process_dhclient_rfc3442_routes(const char * iface,
+ const char * str,
+ NML3ConfigData *l3cd,
+ guint32 * gwaddr)
{
gs_free const char **octets = NULL;
const char *const * o;
@@ -189,9 +189,12 @@ ip4_process_dhclient_rfc3442_routes(const char * iface,
/* normal route */
route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
- route.metric = route_metric;
- route.table_coerced = nm_platform_route_table_coerce(route_table);
- nm_ip4_config_add_route(ip4_config, &route, NULL);
+ route.table_any = TRUE;
+ route.table_coerced = 0;
+ route.metric_any = TRUE;
+ route.metric = 0;
+
+ nm_l3_config_data_add_route_4(l3cd, &route);
_LOG2I(LOGD_DHCP4,
iface,
@@ -206,17 +209,15 @@ ip4_process_dhclient_rfc3442_routes(const char * iface,
}
static gboolean
-ip4_process_classless_routes(const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config,
- guint32 * gwaddr)
+ip4_process_classless_routes(const char * iface,
+ GHashTable * options,
+ NML3ConfigData *l3cd,
+ guint32 * gwaddr)
{
const char *str, *p;
g_return_val_if_fail(options != NULL, FALSE);
- g_return_val_if_fail(ip4_config != NULL, FALSE);
+ g_return_val_if_fail(l3cd != NULL, FALSE);
*gwaddr = 0;
@@ -265,28 +266,14 @@ ip4_process_classless_routes(const char * iface,
if (strchr(str, '/')) {
/* dhcpcd format */
- return ip4_process_dhcpcd_rfc3442_routes(iface,
- str,
- route_table,
- route_metric,
- ip4_config,
- gwaddr);
+ return ip4_process_dhcpcd_rfc3442_routes(iface, str, l3cd, gwaddr);
}
- return ip4_process_dhclient_rfc3442_routes(iface,
- str,
- route_table,
- route_metric,
- ip4_config,
- gwaddr);
+ return ip4_process_dhclient_rfc3442_routes(iface, str, l3cd, gwaddr);
}
static void
-process_classful_routes(const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config)
+process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData *l3cd)
{
gs_free const char **searches = NULL;
const char ** s;
@@ -320,8 +307,10 @@ process_classful_routes(const char * iface,
// FIXME: ensure the IP address and route are sane
- memset(&route, 0, sizeof(route));
- route.network = rt_addr;
+ route = (NMPlatformIP4Route){
+ .network = rt_addr,
+ };
+
/* RFC 2132, updated by RFC 3442:
* The Static Routes option (option 33) does not provide a subnet mask
* for each route - it is assumed that the subnet mask is implicit in
@@ -333,12 +322,15 @@ process_classful_routes(const char * iface,
}
route.gateway = rt_route;
route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
- route.metric = route_metric;
- route.table_coerced = nm_platform_route_table_coerce(route_table);
+ route.table_any = TRUE;
+ route.table_coerced = 0;
+ route.metric_any = TRUE;
+ route.metric = 0;
route.network = nm_utils_ip4_address_clear_host_address(route.network, route.plen);
- nm_ip4_config_add_route(ip4_config, &route, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &route);
+
_LOG2I(LOGD_DHCP,
iface,
" static route %s",
@@ -347,7 +339,7 @@ process_classful_routes(const char * iface,
}
static void
-process_domain_search(const char *iface, const char *str, GFunc add_func, gpointer user_data)
+process_domain_search(int addr_family, const char *iface, const char *str, NML3ConfigData *l3cd)
{
gs_free const char **searches = NULL;
gs_free char * unescaped = NULL;
@@ -356,7 +348,7 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint
int i;
g_return_if_fail(str != NULL);
- g_return_if_fail(add_func != NULL);
+ nm_assert(l3cd);
unescaped = g_strdup(str);
@@ -379,46 +371,43 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint
searches = nm_strsplit_set(unescaped, " ");
for (s = searches; searches && *s; s++) {
_LOG2I(LOGD_DHCP, iface, " domain search '%s'", *s);
- add_func((gpointer) *s, user_data);
+ nm_l3_config_data_add_search(l3cd, addr_family, *s);
}
}
-static void
-ip4_add_domain_search(gpointer data, gpointer user_data)
-{
- nm_ip4_config_add_search(NM_IP4_CONFIG(user_data), (const char *) data);
-}
-
-NMIP4Config *
+NML3ConfigData *
nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
int ifindex,
const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric)
+ GHashTable * options)
{
- gs_unref_object NMIP4Config *ip4_config = NULL;
- guint32 tmp_addr;
- in_addr_t addr;
- NMPlatformIP4Address address;
- char * str = NULL;
- gboolean gateway_has = FALSE;
- guint32 gateway = 0;
- guint8 plen = 0;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ guint32 tmp_addr;
+ in_addr_t addr;
+ NMPlatformIP4Address address;
+ char * str = NULL;
+ gboolean gateway_has = FALSE;
+ guint32 gateway = 0;
+ guint8 plen = 0;
+ char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ guint32 now;
g_return_val_if_fail(options != NULL, NULL);
- ip4_config = nm_ip4_config_new(multi_idx, ifindex);
- memset(&address, 0, sizeof(address));
- address.timestamp = nm_utils_get_monotonic_timestamp_sec();
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
+
+ now = nm_utils_get_monotonic_timestamp_sec();
+
+ address = (NMPlatformIP4Address){
+ .timestamp = now,
+ };
str = g_hash_table_lookup(options, "ip_address");
- if (str && (inet_pton(AF_INET, str, &addr) > 0))
- _LOG2I(LOGD_DHCP4, iface, " address %s", str);
- else
+ if (!str || !nm_utils_parse_inaddr_bin(AF_INET, str, NULL, &addr))
return NULL;
+ _LOG2I(LOGD_DHCP4, iface, " address %s", str);
+
str = g_hash_table_lookup(options, "subnet_mask");
if (str && (inet_pton(AF_INET, str, &tmp_addr) > 0)) {
plen = nm_utils_ip4_netmask_to_prefix(tmp_addr);
@@ -433,13 +422,8 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
/* Routes: if the server returns classless static routes, we MUST ignore
* the 'static_routes' option.
*/
- if (!ip4_process_classless_routes(iface,
- options,
- route_table,
- route_metric,
- ip4_config,
- &gateway))
- process_classful_routes(iface, options, route_table, route_metric, ip4_config);
+ if (!ip4_process_classless_routes(iface, options, l3cd, &gateway))
+ process_classful_routes(iface, options, l3cd);
if (gateway) {
_LOG2I(LOGD_DHCP4, iface, " gateway %s", _nm_utils_inet4_ntop(gateway, sbuf));
@@ -453,7 +437,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
gs_free const char **routers = nm_strsplit_set(str, " ");
const char ** s;
- for (s = routers; routers && *s; s++) {
+ for (s = routers; *s; s++) {
/* FIXME: how to handle multiple routers? */
if (inet_pton(AF_INET, *s, &gateway) > 0) {
_LOG2I(LOGD_DHCP4, iface, " gateway %s", *s);
@@ -469,11 +453,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
const NMPlatformIP4Route r = {
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
.gateway = gateway,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
- nm_ip4_config_add_route(ip4_config, &r, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &r);
}
str = g_hash_table_lookup(options, "dhcp_lease_time");
@@ -483,7 +469,8 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
}
address.addr_source = NM_IP_CONFIG_SOURCE_DHCP;
- nm_ip4_config_add_address(ip4_config, &address);
+
+ nm_l3_config_data_add_address_4(l3cd, &address);
str = g_hash_table_lookup(options, "host_name");
if (str)
@@ -497,7 +484,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = dns; dns && *s; s++) {
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
- nm_ip4_config_add_nameserver(ip4_config, tmp_addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &tmp_addr);
_LOG2I(LOGD_DHCP4, iface, " nameserver '%s'", *s);
}
} else
@@ -512,13 +499,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = domains; domains && *s; s++) {
_LOG2I(LOGD_DHCP4, iface, " domain name '%s'", *s);
- nm_ip4_config_add_domain(ip4_config, *s);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, *s);
}
}
str = g_hash_table_lookup(options, "domain_search");
if (str)
- process_domain_search(iface, str, ip4_add_domain_search, ip4_config);
+ process_domain_search(AF_INET, iface, str, l3cd);
str = g_hash_table_lookup(options, "netbios_name_servers");
if (str) {
@@ -528,7 +515,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = nbns; nbns && *s; s++) {
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
- nm_ip4_config_add_wins(ip4_config, tmp_addr);
+ nm_l3_config_data_add_wins(l3cd, tmp_addr);
_LOG2I(LOGD_DHCP4, iface, " wins '%s'", *s);
}
} else
@@ -546,13 +533,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
return NULL;
if (int_mtu > 576)
- nm_ip4_config_set_mtu(ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_set_mtu(l3cd, int_mtu);
}
str = g_hash_table_lookup(options, "nis_domain");
if (str) {
_LOG2I(LOGD_DHCP4, iface, " NIS domain '%s'", str);
- nm_ip4_config_set_nis_domain(ip4_config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, str);
}
str = g_hash_table_lookup(options, "nis_servers");
@@ -563,7 +550,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = nis; nis && *s; s++) {
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
- nm_ip4_config_add_nis_server(ip4_config, tmp_addr);
+ nm_l3_config_data_add_nis_server(l3cd, tmp_addr);
_LOG2I(LOGD_DHCP4, iface, " nis '%s'", *s);
}
} else
@@ -572,19 +559,20 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
}
str = g_hash_table_lookup(options, "vendor_encapsulated_options");
- nm_ip4_config_set_metered(ip4_config, str && strstr(str, "ANDROID_METERED"));
+ if (str && strstr(str, "ANDROID_METERED"))
+ nm_l3_config_data_set_metered(l3cd, TRUE);
- return g_steal_pointer(&ip4_config);
+ str = g_hash_table_lookup(options, "wpad");
+ if (str) {
+ nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
+ nm_l3_config_data_set_proxy_pac_url(l3cd, str);
+ }
+
+ return g_steal_pointer(&l3cd);
}
/*****************************************************************************/
-static void
-ip6_add_domain_search(gpointer data, gpointer user_data)
-{
- nm_ip6_config_add_search(NM_IP6_CONFIG(user_data), (const char *) data);
-}
-
NMPlatformIP6Address
nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options)
{
@@ -635,25 +623,29 @@ nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options)
return address;
}
-NMIP6Config *
+NML3ConfigData *
nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
int ifindex,
const char * iface,
GHashTable * options,
gboolean info_only)
{
- gs_unref_object NMIP6Config *ip6_config = NULL;
- struct in6_addr tmp_addr;
- NMPlatformIP6Address address;
- char * str = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ struct in6_addr tmp_addr;
+ NMPlatformIP6Address address;
+ char * str = NULL;
+ guint32 now;
g_return_val_if_fail(options != NULL, NULL);
- memset(&address, 0, sizeof(address));
- address.plen = 128;
- address.timestamp = nm_utils_get_monotonic_timestamp_sec();
+ now = nm_utils_get_monotonic_timestamp_sec();
- ip6_config = nm_ip6_config_new(multi_idx, ifindex);
+ address = (NMPlatformIP6Address){
+ .plen = 128,
+ .timestamp = now,
+ };
+
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
str = g_hash_table_lookup(options, "max_life");
if (str) {
@@ -676,7 +668,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
address.address = tmp_addr;
address.addr_source = NM_IP_CONFIG_SOURCE_DHCP;
- nm_ip6_config_add_address(ip6_config, &address);
+ nm_l3_config_data_add_address_6(l3cd, &address);
_LOG2I(LOGD_DHCP6, iface, " address %s", str);
} else if (info_only == FALSE) {
/* No address in Managed mode is a hard error */
@@ -695,7 +687,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = dns; dns && *s; s++) {
if (inet_pton(AF_INET6, *s, &tmp_addr) > 0) {
if (!IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
- nm_ip6_config_add_nameserver(ip6_config, &tmp_addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &tmp_addr);
_LOG2I(LOGD_DHCP6, iface, " nameserver '%s'", *s);
}
} else
@@ -705,9 +697,9 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
str = g_hash_table_lookup(options, "dhcp6_domain_search");
if (str)
- process_domain_search(iface, str, ip6_add_domain_search, ip6_config);
+ process_domain_search(AF_INET6, iface, str, l3cd);
- return g_steal_pointer(&ip6_config);
+ return g_steal_pointer(&l3cd);
}
char *
@@ -838,6 +830,65 @@ nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease)
return g_strdup_printf("%s|%s", iaid, start);
}
+gboolean
+nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData * l3cd_old,
+ const NML3ConfigData * l3cd_new,
+ const NML3ConfigData **out_l3cd_merged)
+{
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd_merged = NULL;
+ const NMPlatformIP6Address * addr;
+ NMDhcpLease * lease_old;
+ NMDhcpLease * lease_new;
+ NMDedupMultiIter iter;
+ const char * start;
+ const char * iaid;
+
+ nm_assert(out_l3cd_merged);
+ nm_assert(!*out_l3cd_merged);
+
+ if (!l3cd_old)
+ return FALSE;
+ if (!l3cd_new)
+ return FALSE;
+
+ lease_new = nm_l3_config_data_get_dhcp_lease(l3cd_new, AF_INET6);
+ if (!lease_new)
+ return FALSE;
+
+ lease_old = nm_l3_config_data_get_dhcp_lease(l3cd_old, AF_INET6);
+ if (!lease_old)
+ return FALSE;
+
+ start = nm_dhcp_lease_lookup_option(lease_new, "life_starts");
+ if (!start)
+ return FALSE;
+ iaid = nm_dhcp_lease_lookup_option(lease_new, "iaid");
+ if (!iaid)
+ return FALSE;
+
+ if (!nm_streq0(start, nm_dhcp_lease_lookup_option(lease_old, "life_starts")))
+ return FALSE;
+ if (!nm_streq0(iaid, nm_dhcp_lease_lookup_option(lease_old, "iaid")))
+ return FALSE;
+
+ /* If the server sends multiple IPv6 addresses, we receive a state
+ * changed event for each of them. Use the event ID to merge IPv6
+ * addresses from the same transaction into a single configuration.
+ **/
+
+ l3cd_merged = nm_l3_config_data_new_clone(l3cd_old, -1);
+
+ nm_l3_config_data_iter_ip6_address_for_each (&iter, l3cd_new, &addr)
+ nm_l3_config_data_add_address_6(l3cd_merged, addr);
+
+ /* FIXME(l3cfg): Note that we keep the original NMDhcpLease. All we take from the new lease are the
+ * addresses. Maybe this is not right and we should merge the leases too?? */
+ nm_l3_config_data_set_dhcp_lease(l3cd_merged, AF_INET6, lease_old);
+
+ *out_l3cd_merged = nm_l3_config_data_ref_and_seal(g_steal_pointer(&l3cd_merged));
+ return TRUE;
+}
+
/*****************************************************************************/
gboolean
diff --git a/src/core/dhcp/nm-dhcp-utils.h b/src/core/dhcp/nm-dhcp-utils.h
index 69715f90fe..bee10de3f6 100644
--- a/src/core/dhcp/nm-dhcp-utils.h
+++ b/src/core/dhcp/nm-dhcp-utils.h
@@ -8,21 +8,18 @@
#include <stdlib.h>
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
-
-NMIP4Config *nm_dhcp_utils_ip4_config_from_options(struct _NMDedupMultiIndex *multi_idx,
- int ifindex,
- const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric);
-
-NMIP6Config *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
- int ifindex,
- const char * iface,
- GHashTable * options,
- gboolean info_only);
+#include "nm-l3-config-data.h"
+
+NML3ConfigData *nm_dhcp_utils_ip4_config_from_options(struct _NMDedupMultiIndex *multi_idx,
+ int ifindex,
+ const char * iface,
+ GHashTable * options);
+
+NML3ConfigData *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
+ int ifindex,
+ const char * iface,
+ GHashTable * options,
+ gboolean info_only);
NMPlatformIP6Address nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options);
@@ -38,6 +35,10 @@ gboolean nm_dhcp_utils_get_leasefile_path(int addr_family,
char *nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease);
+gboolean nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData * l3cd_old,
+ const NML3ConfigData * l3cd_new,
+ const NML3ConfigData **out_l3cd_merged);
+
/*****************************************************************************/
static inline gboolean
diff --git a/src/core/dhcp/tests/test-dhcp-dhclient.c b/src/core/dhcp/tests/test-dhcp-dhclient.c
index e9a6209644..803933ff04 100644
--- a/src/core/dhcp/tests/test-dhcp-dhclient.c
+++ b/src/core/dhcp/tests/test-dhcp-dhclient.c
@@ -15,7 +15,6 @@
#include "dhcp/nm-dhcp-dhclient-utils.h"
#include "dhcp/nm-dhcp-utils.h"
#include "nm-utils.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-test-utils-core.h"
diff --git a/src/core/dhcp/tests/test-dhcp-utils.c b/src/core/dhcp/tests/test-dhcp-utils.c
index 4d47e7e283..0fab5c15ad 100644
--- a/src/core/dhcp/tests/test-dhcp-utils.c
+++ b/src/core/dhcp/tests/test-dhcp-utils.c
@@ -20,20 +20,18 @@
/*****************************************************************************/
-static NMIP4Config *
-_ip4_config_from_options(int ifindex, const char *iface, GHashTable *options, guint32 route_metric)
+static const NML3ConfigData *
+_ip4_config_from_options(int ifindex, const char *iface, GHashTable *options)
{
nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = nm_dedup_multi_index_new();
- NMIP4Config * config;
-
- config = nm_dhcp_utils_ip4_config_from_options(multi_idx,
- ifindex,
- iface,
- options,
- RT_TABLE_MAIN,
- route_metric);
- g_assert(config);
- return config;
+ NML3ConfigData * l3cd;
+
+ l3cd = nm_dhcp_utils_ip4_config_from_options(multi_idx, ifindex, iface, options);
+ g_assert(NM_IS_L3_CONFIG_DATA(l3cd));
+ g_assert(!nm_l3_config_data_is_sealed(l3cd));
+ if (nmtst_get_rand_bool())
+ nm_l3_config_data_seal(l3cd);
+ return l3cd;
}
typedef struct {
@@ -74,58 +72,57 @@ static const Option generic_options[] = {
static void
test_generic_options(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
- const NMPlatformIP4Route * route;
- guint32 tmp;
- const char * expected_addr = "192.168.1.106";
- const char * expected_gw = "192.168.1.1";
- const char * expected_dns1 = "216.254.95.2";
- const char * expected_dns2 = "216.231.41.2";
- const char * expected_search1 = "foobar.com";
- const char * expected_search2 = "blah.foobar.com";
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
-
- options = fill_table(generic_options, NULL);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
-
- /* IP4 address */
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
+ const NMPlatformIP4Route * route;
+ guint32 tmp;
+ const char * expected_addr = "192.168.1.106";
+ const char * expected_gw = "192.168.1.1";
+ const char * expected_dns1 = "216.254.95.2";
+ const char * expected_dns2 = "216.231.41.2";
+ const char * expected_search1 = "foobar.com";
+ const char * expected_search2 = "blah.foobar.com";
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ const char *const * strarr;
+ const in_addr_t * ia_arr;
+ guint u;
+
+ options = fill_table(generic_options, NULL);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
+
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(inet_pton(AF_INET, expected_addr, &tmp) > 0);
g_assert(address->address == tmp);
g_assert(address->peer_address == tmp);
g_assert_cmpint(address->plen, ==, 24);
- /* Gateway */
- g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
- g_assert(nmtst_ip4_config_get_gateway(ip4_config) == tmp);
+ nmtst_assert_ip_address(AF_INET,
+ nmtst_l3_config_data_get_best_gateway(l3cd, AF_INET),
+ expected_gw);
- g_assert_cmpint(nm_ip4_config_get_num_wins(ip4_config), ==, 0);
+ g_assert(!nm_l3_config_data_get_wins(l3cd, &u));
+ g_assert_cmpint(u, ==, 0);
- g_assert_cmpint(nm_ip4_config_get_mtu(ip4_config), ==, 987);
+ g_assert_cmpint(nm_l3_config_data_get_mtu(l3cd), ==, 987);
- /* Domain searches */
- g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 2);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 0), ==, expected_search1);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 1), ==, expected_search2);
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 2);
+ g_assert_cmpstr(strarr[0], ==, expected_search1);
+ g_assert_cmpstr(strarr[1], ==, expected_search2);
- /* DNS servers */
- g_assert_cmpint(nm_ip4_config_get_num_nameservers(ip4_config), ==, 2);
- g_assert(inet_pton(AF_INET, expected_dns1, &tmp) > 0);
- g_assert(nm_ip4_config_get_nameserver(ip4_config, 0) == tmp);
- g_assert(inet_pton(AF_INET, expected_dns2, &tmp) > 0);
- g_assert(nm_ip4_config_get_nameserver(ip4_config, 1) == tmp);
+ ia_arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 2);
+ nmtst_assert_ip4_address(ia_arr[0], expected_dns1);
+ nmtst_assert_ip4_address(ia_arr[1], expected_dns2);
- /* Routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
- /* Route #1 */
- route = _nmtst_ip4_config_get_route(ip4_config, 0);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, 0);
g_assert(inet_pton(AF_INET, expected_route1_dest, &tmp) > 0);
g_assert(route->network == tmp);
g_assert(inet_pton(AF_INET, expected_route1_gw, &tmp) > 0);
@@ -133,69 +130,63 @@ test_generic_options(void)
g_assert_cmpint(route->plen, ==, 32);
g_assert_cmpint(route->metric, ==, 0);
- /* Route #2 */
- route = _nmtst_ip4_config_get_route(ip4_config, 1);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, 1);
g_assert(route->network == nmtst_inet4_from_string(expected_route2_dest));
g_assert(route->gateway == nmtst_inet4_from_string(expected_route2_gw));
g_assert_cmpint(route->plen, ==, 32);
g_assert_cmpint(route->metric, ==, 0);
- route = _nmtst_ip4_config_get_route(ip4_config, 2);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, 2);
g_assert(route->network == nmtst_inet4_from_string("0.0.0.0"));
g_assert(route->gateway == nmtst_inet4_from_string("192.168.1.1"));
g_assert_cmpint(route->plen, ==, 0);
g_assert_cmpint(route->metric, ==, 0);
-
- g_hash_table_destroy(options);
}
static void
test_wins_options(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
- guint32 tmp;
- const char * expected_wins1 = "63.12.199.5";
- const char * expected_wins2 = "150.4.88.120";
- static const Option data[] = {{"netbios_name_servers", "63.12.199.5 150.4.88.120"},
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
+ const char * expected_wins1 = "63.12.199.5";
+ const char * expected_wins2 = "150.4.88.120";
+ static const Option data[] = {{"netbios_name_servers", "63.12.199.5 150.4.88.120"},
{NULL, NULL}};
+ const in_addr_t * ia_arr;
+ guint u;
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- /* IP4 address */
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(address);
- g_assert_cmpint(nm_ip4_config_get_num_wins(ip4_config), ==, 2);
- g_assert(inet_pton(AF_INET, expected_wins1, &tmp) > 0);
- g_assert(nm_ip4_config_get_wins(ip4_config, 0) == tmp);
- g_assert(inet_pton(AF_INET, expected_wins2, &tmp) > 0);
- g_assert(nm_ip4_config_get_wins(ip4_config, 1) == tmp);
- g_hash_table_destroy(options);
+ ia_arr = nm_l3_config_data_get_wins(l3cd, &u);
+ g_assert_cmpint(u, ==, 2);
+ nmtst_assert_ip4_address(ia_arr[0], expected_wins1);
+ nmtst_assert_ip4_address(ia_arr[1], expected_wins2);
}
static void
test_vendor_option_metered(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
static const Option data[] = {{"vendor_encapsulated_options", "ANDROID_METERED"}, {NULL, NULL}};
- options = fill_table(generic_options, NULL);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
- g_assert(nm_ip4_config_get_metered(ip4_config) == FALSE);
- g_hash_table_destroy(options);
- g_clear_object(&ip4_config);
-
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
- g_assert(nm_ip4_config_get_metered(ip4_config) == TRUE);
- g_hash_table_destroy(options);
+ options = fill_table(generic_options, NULL);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
+ g_assert(nm_l3_config_data_get_metered(l3cd) == NM_TERNARY_DEFAULT);
+ nm_clear_pointer(&options, g_hash_table_destroy);
+ nm_clear_l3cd(&l3cd);
+
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
+ g_assert(nm_l3_config_data_get_metered(l3cd) == TRUE);
}
static void
@@ -252,18 +243,18 @@ test_parse_search_list(void)
}
static void
-ip4_test_route(NMIP4Config *ip4_config,
- guint route_num,
- const char * expected_dest,
- const char * expected_gw,
- guint expected_prefix)
+ip4_test_route(const NML3ConfigData *l3cd,
+ guint route_num,
+ const char * expected_dest,
+ const char * expected_gw,
+ guint expected_prefix)
{
const NMPlatformIP4Route *route;
guint32 tmp;
g_assert(expected_prefix <= 32);
- route = _nmtst_ip4_config_get_route(ip4_config, route_num);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, route_num);
g_assert(inet_pton(AF_INET, expected_dest, &tmp) > 0);
g_assert(route->network == tmp);
g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
@@ -272,110 +263,105 @@ ip4_test_route(NMIP4Config *ip4_config,
g_assert_cmpint(route->metric, ==, 0);
}
-static void
-ip4_test_gateway(NMIP4Config *ip4_config, const char *expected_gw)
-{
- guint32 tmp;
-
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
- g_assert(nmtst_ip4_config_get_gateway(ip4_config) == tmp);
-}
+#define ip4_test_gateway(l3cd, expected_gw) \
+ G_STMT_START \
+ { \
+ const NML3ConfigData *_l3cd = (l3cd); \
+ \
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(_l3cd, AF_INET), ==, 1); \
+ nmtst_assert_ip_address(AF_INET, \
+ nmtst_l3_config_data_get_best_gateway(_l3cd, AF_INET), \
+ expected_gw); \
+ } \
+ G_STMT_END
static void
test_classless_static_routes_1(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_route2_dest = "10.0.0.0";
- const char * expected_route2_gw = "10.17.66.41";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_route2_dest = "10.0.0.0";
+ const char * expected_route2_gw = "10.17.66.41";
+ static const Option data[] = {
/* dhclient custom format */
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 8 10 10 17 66 41"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 8);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_classless_static_routes_2(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_route2_dest = "10.0.0.0";
- const char * expected_route2_gw = "10.17.66.41";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_route2_dest = "10.0.0.0";
+ const char * expected_route2_gw = "10.17.66.41";
+ static const Option data[] = {
/* dhcpcd format */
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
- ip4_test_route(ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 8);
+ ip4_test_route(l3cd, 2, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_fedora_dhclient_classless_static_routes(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "129.210.177.128";
- const char * expected_route1_gw = "192.168.0.113";
- const char * expected_route2_dest = "2.0.0.0";
- const char * expected_route2_gw = "10.34.255.6";
- const char * expected_gateway = "192.168.0.113";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "129.210.177.128";
+ const char * expected_route1_gw = "192.168.0.113";
+ const char * expected_route2_dest = "2.0.0.0";
+ const char * expected_route2_gw = "10.34.255.6";
+ const char * expected_gateway = "192.168.0.113";
+ static const Option data[] = {
/* Fedora dhclient format */
{"classless_static_routes",
"0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 25);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 7);
- ip4_test_route(ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 25);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 7);
+ ip4_test_route(l3cd, 2, "0.0.0.0", expected_route1_gw, 0);
- /* Gateway */
- ip4_test_gateway(ip4_config, expected_gateway);
-
- g_hash_table_destroy(options);
+ ip4_test_gateway(l3cd, expected_gateway);
}
static void
test_dhclient_invalid_classless_routes_1(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ static const Option data[] = {
/* dhclient format */
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 45 10 17 66 41"},
{NULL, NULL}};
@@ -384,27 +370,25 @@ test_dhclient_invalid_classless_routes_1(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_dhcpcd_invalid_classless_routes_1(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ static const Option data[] = {
/* dhcpcd format */
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.adfadf/44 10.17.66.41"},
{NULL, NULL}};
@@ -413,30 +397,28 @@ test_dhcpcd_invalid_classless_routes_1(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* Test falling back to old-style static routes if the classless static
* routes are invalid.
*/
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_dhclient_invalid_classless_routes_2(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ static const Option data[] = {
{"rfc3442_classless_static_routes", "45 10 17 66 41 24 192 168 10 192 168 1 1"},
{NULL, NULL}};
@@ -444,30 +426,28 @@ test_dhclient_invalid_classless_routes_2(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* Test falling back to old-style static routes if the classless static
* routes are invalid.
*/
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_dhcpcd_invalid_classless_routes_2(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ static const Option data[] = {
{"classless_static_routes", "10.0.adfadf/44 10.17.66.41 192.168.10.0/24 192.168.1.1"},
{NULL, NULL}};
@@ -475,7 +455,7 @@ test_dhcpcd_invalid_classless_routes_2(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* Test falling back to old-style static routes if the classless static
@@ -483,22 +463,20 @@ test_dhcpcd_invalid_classless_routes_2(void)
*/
/* Routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_dhclient_invalid_classless_routes_3(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ static const Option data[] = {
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 32 128 10 17 66 41"},
{NULL, NULL}};
@@ -506,25 +484,23 @@ test_dhclient_invalid_classless_routes_3(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_dhcpcd_invalid_classless_routes_3(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- static Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ static Option data[] = {
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 128/32 10.17.66.41"},
{NULL, NULL}};
@@ -532,133 +508,124 @@ test_dhcpcd_invalid_classless_routes_3(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*DHCP provided invalid classless static route*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_dhclient_gw_in_classless_routes(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_gateway = "192.2.3.4";
- static Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_gateway = "192.2.3.4";
+ static Option data[] = {
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 0 192 2 3 4"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
-
- /* Gateway */
- ip4_test_gateway(ip4_config, expected_gateway);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", "192.2.3.4", 0);
- g_hash_table_destroy(options);
+ ip4_test_gateway(l3cd, expected_gateway);
}
static void
test_dhcpcd_gw_in_classless_routes(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_gateway = "192.2.3.4";
- static Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_gateway = "192.2.3.4";
+ static Option data[] = {
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 0.0.0.0/0 192.2.3.4"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
-
- /* Gateway */
- ip4_test_gateway(ip4_config, expected_gateway);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", "192.2.3.4", 0);
- g_hash_table_destroy(options);
+ ip4_test_gateway(l3cd, expected_gateway);
}
static void
test_escaped_domain_searches(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_search0 = "host1";
- const char * expected_search1 = "host2";
- const char * expected_search2 = "host3";
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_search0 = "host1";
+ const char * expected_search1 = "host2";
+ const char * expected_search2 = "host3";
static const Option data[] = {{"domain_search", "host1\\032host2\\032host3"}, {NULL, NULL}};
+ const char *const * strarr;
+ guint u;
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
-
- /* domain searches */
- g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 3);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 0), ==, expected_search0);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 1), ==, expected_search1);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 2), ==, expected_search2);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- g_hash_table_destroy(options);
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 3);
+ g_assert_cmpstr(strarr[0], ==, expected_search0);
+ g_assert_cmpstr(strarr[1], ==, expected_search1);
+ g_assert_cmpstr(strarr[2], ==, expected_search2);
}
static void
test_invalid_escaped_domain_searches(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
static const Option data[] = {{"domain_search", "host1\\aahost2\\032host3"}, {NULL, NULL}};
+ const char *const * strarr;
+ guint u;
options = fill_table(generic_options, NULL);
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*invalid domain search*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
- /* domain searches */
- g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 0);
-
- g_hash_table_destroy(options);
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 0);
+ g_assert(!strarr);
}
static void
test_ip4_missing_prefix(const char *ip, guint32 expected_prefix)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
options = fill_table(generic_options, NULL);
g_hash_table_insert(options, "ip_address", (gpointer) ip);
g_hash_table_remove(options, "subnet_mask");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(address);
g_assert_cmpint(address->plen, ==, expected_prefix);
-
- g_hash_table_destroy(options);
}
static void
@@ -682,9 +649,9 @@ test_ip4_missing_prefix_8(void)
static void
test_ip4_prefix_classless(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
/* Ensure that the missing-subnet-mask handler doesn't mangle classless
* subnet masks at all. The handler should trigger only if the server
@@ -695,14 +662,12 @@ test_ip4_prefix_classless(void)
g_hash_table_insert(options, "ip_address", "172.16.54.22");
g_hash_table_insert(options, "subnet_mask", "255.255.252.0");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(address);
g_assert_cmpint(address->plen, ==, 22);
-
- g_hash_table_destroy(options);
}
#define COMPARE_ID(src, is_str, expected, expected_len) \
diff --git a/src/core/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c
index 126e0a217a..b40521a32b 100644
--- a/src/core/dns/nm-dns-dnsmasq.c
+++ b/src/core/dns/nm-dns-dnsmasq.c
@@ -19,10 +19,9 @@
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-platform/nm-platform.h"
#include "nm-utils.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "nm-dbus-manager.h"
#include "NetworkManagerUtils.h"
+#include "nm-l3-config-data.h"
#define PIDFILE NMRUNDIR "/dnsmasq.pid"
#define CONFDIR NMCONFDIR "/dnsmasq.d"
@@ -806,20 +805,22 @@ add_global_config(NMDnsDnsmasq * self,
static void
add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsConfigIPData *ip_data)
{
- NMIPConfig * ip_config = ip_data->ip_config;
- gconstpointer addr;
- const char * iface, *domain;
+ const char * iface;
+ const char * domain;
char ip_addr_to_string_buf[IP_ADDR_TO_STRING_BUFLEN];
- int addr_family;
- guint i, j, num;
+ gconstpointer nameservers;
+ guint num;
+ guint i;
+ guint j;
- iface = nm_platform_link_get_name(NM_PLATFORM_GET, ip_data->data->ifindex);
- addr_family = nm_ip_config_get_addr_family(ip_config);
+ iface = nm_platform_link_get_name(NM_PLATFORM_GET, ip_data->data->ifindex);
- num = nm_ip_config_get_num_nameservers(ip_config);
+ nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
for (i = 0; i < num; i++) {
- addr = nm_ip_config_get_nameserver(ip_config, i);
- ip_addr_to_string(addr_family, addr, iface, ip_addr_to_string_buf);
+ gconstpointer addr;
+
+ addr = nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i);
+ ip_addr_to_string(ip_data->addr_family, addr, iface, ip_addr_to_string_buf);
if (!ip_data->domains.has_default_route_explicit && ip_data->domains.has_default_route)
add_dnsmasq_nameserver(self, servers, ip_addr_to_string_buf, NULL);
@@ -846,7 +847,7 @@ add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsConfigIPD
static GVariant *
create_update_args(NMDnsDnsmasq * self,
const NMGlobalDnsConfig *global_config,
- const CList * ip_config_lst_head,
+ const CList * ip_data_lst_head,
const char * hostname)
{
GVariantBuilder servers;
@@ -857,7 +858,7 @@ create_update_args(NMDnsDnsmasq * self,
if (global_config)
add_global_config(self, &servers, global_config);
else {
- c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst)
+ c_list_for_each_entry (ip_data, ip_data_lst_head, ip_data_lst)
add_ip_config(self, &servers, ip_data);
}
@@ -1122,7 +1123,7 @@ start_dnsmasq(NMDnsDnsmasq *self, gboolean force_start, GError **error)
static gboolean
update(NMDnsPlugin * plugin,
const NMGlobalDnsConfig *global_config,
- const CList * ip_config_lst_head,
+ const CList * ip_data_lst_head,
const char * hostname,
GError ** error)
{
@@ -1134,7 +1135,7 @@ update(NMDnsPlugin * plugin,
nm_clear_pointer(&priv->set_server_ex_args, g_variant_unref);
priv->set_server_ex_args =
- g_variant_ref_sink(create_update_args(self, global_config, ip_config_lst_head, hostname));
+ g_variant_ref_sink(create_update_args(self, global_config, ip_data_lst_head, hostname));
send_dnsmasq_update(self);
return TRUE;
diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c
index f0ec0c8921..1ca33e46ac 100644
--- a/src/core/dns/nm-dns-manager.c
+++ b/src/core/dns/nm-dns-manager.c
@@ -7,6 +7,8 @@
#include "src/core/nm-default-daemon.h"
+#include "nm-dns-manager.h"
+
#include <fcntl.h>
#include <resolv.h>
#include <stdlib.h>
@@ -22,22 +24,20 @@
#include <libpsl.h>
#endif
-#include "libnm-glib-aux/nm-str-buf.h"
-#include "nm-utils.h"
#include "libnm-core-intern/nm-core-internal.h"
-#include "nm-dns-manager.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "libnm-glib-aux/nm-str-buf.h"
+
#include "NetworkManagerUtils.h"
+#include "devices/nm-device.h"
#include "nm-config.h"
#include "nm-dbus-object.h"
-#include "devices/nm-device.h"
-#include "nm-manager.h"
-
-#include "nm-dns-plugin.h"
#include "nm-dns-dnsmasq.h"
+#include "nm-dns-plugin.h"
#include "nm-dns-systemd-resolved.h"
#include "nm-dns-unbound.h"
+#include "nm-l3-config-data.h"
+#include "nm-manager.h"
+#include "nm-utils.h"
#define HASH_LEN NM_UTILS_CHECKSUM_LENGTH_SHA1
@@ -84,22 +84,21 @@ typedef struct {
GHashTable *configs_dict;
CList configs_lst_head;
- CList ip_config_lst_head;
+ CList ip_data_lst_head;
GVariant *config_variant;
- bool ip_config_lst_need_sort : 1;
+ bool ip_data_lst_need_sort : 1;
bool configs_lst_need_sort : 1;
bool dns_touched : 1;
bool is_stopped : 1;
+ bool config_changed : 1;
+
char *hostname;
guint updates_queue;
- guint8 hash[HASH_LEN]; /* SHA1 hash of current DNS config */
- guint8 prev_hash[HASH_LEN]; /* Hash when begin_updates() was called */
-
NMDnsManagerResolvConfManager rc_manager;
char * mode;
NMDnsPlugin * sd_resolve_plugin;
@@ -159,11 +158,6 @@ NM_DEFINE_SINGLETON_GETTER(NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER
/*****************************************************************************/
-static void
-_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigIPData *ip_data);
-
-/*****************************************************************************/
-
static gboolean
domain_is_valid(const char *domain, gboolean check_public_suffix)
{
@@ -208,6 +202,24 @@ static NM_UTILS_LOOKUP_STR_DEFINE(
/*****************************************************************************/
+static int
+_dns_config_ip_data_get_dns_priority1(const NML3ConfigData *l3cd, int addr_family)
+{
+ int prio;
+
+ if (!nm_l3_config_data_get_dns_priority(l3cd, addr_family, &prio))
+ return 0;
+
+ nm_assert(prio != 0);
+ return prio;
+}
+
+static int
+_dns_config_ip_data_get_dns_priority(const NMDnsConfigIPData *ip_data)
+{
+ return _dns_config_ip_data_get_dns_priority1(ip_data->l3cd, ip_data->addr_family);
+}
+
static void
_ASSERT_dns_config_data(const NMDnsConfigData *data)
{
@@ -221,9 +233,9 @@ _ASSERT_dns_config_ip_data(const NMDnsConfigIPData *ip_data)
{
nm_assert(ip_data);
_ASSERT_dns_config_data(ip_data->data);
- nm_assert(NM_IS_IP_CONFIG(ip_data->ip_config));
+ nm_assert(NM_IS_L3_CONFIG_DATA(ip_data->l3cd));
nm_assert(c_list_contains(&ip_data->data->data_lst_head, &ip_data->data_lst));
- nm_assert(ip_data->data->ifindex == nm_ip_config_get_ifindex(ip_data->ip_config));
+ nm_assert(ip_data->data->ifindex == nm_l3_config_data_get_ifindex(ip_data->l3cd));
#if NM_MORE_ASSERTS > 5
{
gboolean has_default = FALSE;
@@ -243,37 +255,36 @@ _ASSERT_dns_config_ip_data(const NMDnsConfigIPData *ip_data)
if (ip_data->domains.has_default_route_exclusive)
nm_assert(ip_data->domains.has_default_route);
}
+ nm_assert(_dns_config_ip_data_get_dns_priority(ip_data) != 0);
#endif
}
static NMDnsConfigIPData *
-_dns_config_ip_data_new(NMDnsConfigData * data,
- NMIPConfig * ip_config,
- NMDnsIPConfigType ip_config_type)
+_dns_config_ip_data_new(NMDnsConfigData * data,
+ int addr_family,
+ gconstpointer source_tag,
+ const NML3ConfigData *l3cd,
+ NMDnsIPConfigType ip_config_type)
{
NMDnsConfigIPData *ip_data;
_ASSERT_dns_config_data(data);
- nm_assert(NM_IS_IP_CONFIG(ip_config));
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED);
ip_data = g_slice_new(NMDnsConfigIPData);
*ip_data = (NMDnsConfigIPData){
.data = data,
- .ip_config = g_object_ref(ip_config),
+ .source_tag = source_tag,
+ .l3cd = nm_l3_config_data_ref_and_seal(l3cd),
.ip_config_type = ip_config_type,
+ .addr_family = addr_family,
};
c_list_link_tail(&data->data_lst_head, &ip_data->data_lst);
- c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_config_lst_head,
- &ip_data->ip_config_lst);
-
- /* We also need to set priv->ip_config_lst_need_sort, but the caller will do that! */
+ c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_data_lst_head,
+ &ip_data->ip_data_lst);
- g_signal_connect(ip_config,
- NM_IS_IP4_CONFIG(ip_config) ? "notify::" NM_IP4_CONFIG_DNS_PRIORITY
- : "notify::" NM_IP6_CONFIG_DNS_PRIORITY,
- G_CALLBACK(_ip_config_dns_priority_changed),
- ip_data);
+ /* We also need to set priv->ip_data_lst_need_sort, but the caller will do that! */
_ASSERT_dns_config_ip_data(ip_data);
return ip_data;
@@ -285,35 +296,15 @@ _dns_config_ip_data_free(NMDnsConfigIPData *ip_data)
_ASSERT_dns_config_ip_data(ip_data);
c_list_unlink_stale(&ip_data->data_lst);
- c_list_unlink_stale(&ip_data->ip_config_lst);
+ c_list_unlink_stale(&ip_data->ip_data_lst);
g_free(ip_data->domains.search);
g_strfreev(ip_data->domains.reverse);
- g_signal_handlers_disconnect_by_func(ip_data->ip_config,
- _ip_config_dns_priority_changed,
- ip_data);
-
- g_object_unref(ip_data->ip_config);
+ nm_l3_config_data_unref(ip_data->l3cd);
nm_g_slice_free(ip_data);
}
-static NMDnsConfigIPData *
-_dns_config_data_find_ip_config(NMDnsConfigData *data, NMIPConfig *ip_config)
-{
- NMDnsConfigIPData *ip_data;
-
- _ASSERT_dns_config_data(data);
-
- c_list_for_each_entry (ip_data, &data->data_lst_head, data_lst) {
- _ASSERT_dns_config_ip_data(ip_data);
-
- if (ip_data->ip_config == ip_config)
- return ip_data;
- }
- return NULL;
-}
-
static void
_dns_config_data_free(NMDnsConfigData *data)
{
@@ -325,14 +316,13 @@ _dns_config_data_free(NMDnsConfigData *data)
}
static int
-_mgr_get_ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data)
+_mgr_get_ip_data_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data)
{
- const NMDnsConfigIPData *a = c_list_entry(a_lst, NMDnsConfigIPData, ip_config_lst);
- const NMDnsConfigIPData *b = c_list_entry(b_lst, NMDnsConfigIPData, ip_config_lst);
+ const NMDnsConfigIPData *a = c_list_entry(a_lst, NMDnsConfigIPData, ip_data_lst);
+ const NMDnsConfigIPData *b = c_list_entry(b_lst, NMDnsConfigIPData, ip_data_lst);
/* Configurations with lower priority value first */
- NM_CMP_DIRECT(nm_ip_config_get_dns_priority(a->ip_config),
- nm_ip_config_get_dns_priority(b->ip_config));
+ NM_CMP_DIRECT(_dns_config_ip_data_get_dns_priority(a), _dns_config_ip_data_get_dns_priority(b));
/* Sort according to type (descendingly) */
NM_CMP_FIELD(b, a, ip_config_type);
@@ -341,16 +331,16 @@ _mgr_get_ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *u
}
static CList *
-_mgr_get_ip_config_lst_head(NMDnsManager *self)
+_mgr_get_ip_data_lst_head(NMDnsManager *self)
{
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self);
- if (G_UNLIKELY(priv->ip_config_lst_need_sort)) {
- priv->ip_config_lst_need_sort = FALSE;
- c_list_sort(&priv->ip_config_lst_head, _mgr_get_ip_config_lst_cmp, NULL);
+ if (G_UNLIKELY(priv->ip_data_lst_need_sort)) {
+ priv->ip_data_lst_need_sort = FALSE;
+ c_list_sort(&priv->ip_data_lst_head, _mgr_get_ip_data_lst_cmp, NULL);
}
- return &priv->ip_config_lst_head;
+ return &priv->ip_data_lst_head;
}
static int
@@ -430,28 +420,33 @@ add_dns_option_item(GPtrArray *array, const char *str)
}
static void
-add_dns_domains(GPtrArray * array,
- const NMIPConfig *ip_config,
- gboolean include_routing,
- gboolean dup)
+add_dns_domains(GPtrArray * array,
+ int addr_family,
+ const NML3ConfigData *l3cd,
+ gboolean include_routing,
+ gboolean dup)
{
- guint num_domains, num_searches, i;
- const char *str;
+ const char *const *domains;
+ const char *const *searches;
+ guint num_domains;
+ guint num_searches;
+ guint i;
+ const char * str;
- num_domains = nm_ip_config_get_num_domains(ip_config);
- num_searches = nm_ip_config_get_num_searches(ip_config);
+ domains = nm_l3_config_data_get_domains(l3cd, addr_family, &num_domains);
+ searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches);
for (i = 0; i < num_searches; i++) {
- str = nm_ip_config_get_search(ip_config, i);
+ str = searches[i];
if (!include_routing && domain_is_routing(str))
continue;
if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE))
continue;
add_string_item(array, str, dup);
}
- if (num_domains > 1 || !num_searches) {
+ if (num_domains > 1 || num_searches == 0) {
for (i = 0; i < num_domains; i++) {
- str = nm_ip_config_get_domain(ip_config, i);
+ str = domains[i];
if (!include_routing && domain_is_routing(str))
continue;
if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE))
@@ -462,26 +457,24 @@ add_dns_domains(GPtrArray * array,
}
static void
-merge_one_ip_config(NMResolvConfData *rc, int ifindex, const NMIPConfig *ip_config)
+merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3ConfigData *l3cd)
{
- int addr_family;
- char buf[NM_UTILS_INET_ADDRSTRLEN + 50];
- gboolean has_trust_ad;
- guint num_nameservers;
- guint num;
- guint i;
-
- addr_family = nm_ip_config_get_addr_family(ip_config);
+ char buf[NM_UTILS_INET_ADDRSTRLEN + 50];
+ gboolean has_trust_ad;
+ guint num_nameservers;
+ guint num;
+ guint i;
+ gconstpointer nameservers;
+ const char *const *strv;
- nm_assert_addr_family(addr_family);
- nm_assert(ifindex > 0);
- nm_assert(ifindex == nm_ip_config_get_ifindex(ip_config));
+ nm_assert(ifindex == nm_l3_config_data_get_ifindex(l3cd));
- num_nameservers = nm_ip_config_get_num_nameservers(ip_config);
+ nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers);
for (i = 0; i < num_nameservers; i++) {
const NMIPAddr *addr;
- addr = nm_ip_config_get_nameserver(ip_config, i);
+ addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i);
+
if (addr_family == AF_INET)
nm_utils_inet_ntop(addr_family, addr, buf);
else if (IN6_IS_ADDR_V4MAPPED(addr))
@@ -502,22 +495,23 @@ merge_one_ip_config(NMResolvConfData *rc, int ifindex, const NMIPConfig *ip_conf
add_string_item(rc->nameservers, buf, TRUE);
}
- add_dns_domains(rc->searches, ip_config, FALSE, TRUE);
+ add_dns_domains(rc->searches, addr_family, l3cd, FALSE, TRUE);
has_trust_ad = FALSE;
- num = nm_ip_config_get_num_dns_options(ip_config);
+ strv = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num);
for (i = 0; i < num; i++) {
- const char *option = nm_ip_config_get_dns_option(ip_config, i);
+ const char *option = strv[i];
if (nm_streq(option, NM_SETTING_DNS_OPTION_TRUST_AD)) {
has_trust_ad = TRUE;
continue;
}
- add_dns_option_item(rc->options, nm_ip_config_get_dns_option(ip_config, i));
+ add_dns_option_item(rc->options, option);
}
+
if (num_nameservers == 0) {
- /* If the @ip_config contributes no DNS servers, ignore whether trust-ad is set or unset
- * for this @ip_config. */
+ /* If the @l3cd contributes no DNS servers, ignore whether trust-ad is set or unset
+ * for this @l3cd. */
} else if (has_trust_ad) {
/* We only set has_trust_ad to TRUE, if all IP configs agree (or don't contribute).
* Once set to FALSE, it doesn't get reset. */
@@ -527,20 +521,17 @@ merge_one_ip_config(NMResolvConfData *rc, int ifindex, const NMIPConfig *ip_conf
rc->has_trust_ad = NM_TERNARY_FALSE;
if (addr_family == AF_INET) {
- const NMIP4Config *ip4_config = (const NMIP4Config *) ip_config;
+ const in_addr_t *nis_servers;
+ const char * nis_domain;
- /* NIS stuff */
- num = nm_ip4_config_get_num_nis_servers(ip4_config);
- for (i = 0; i < num; i++) {
- add_string_item(rc->nis_servers,
- _nm_utils_inet4_ntop(nm_ip4_config_get_nis_server(ip4_config, i), buf),
- TRUE);
- }
+ nis_servers = nm_l3_config_data_get_nis_servers(l3cd, &num);
+ for (i = 0; i < num; i++)
+ add_string_item(rc->nis_servers, _nm_utils_inet4_ntop(nis_servers[i], buf), TRUE);
- if (nm_ip4_config_get_nis_domain(ip4_config)) {
+ if ((nis_domain = nm_l3_config_data_get_nis_domain(l3cd))) {
/* FIXME: handle multiple domains */
if (!rc->nis_domain)
- rc->nis_domain = nm_ip4_config_get_nis_domain(ip4_config);
+ rc->nis_domain = nis_domain;
}
}
}
@@ -1106,30 +1097,6 @@ update_resolv_conf(NMDnsManager * self,
return write_file_result;
}
-static void
-compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[static HASH_LEN])
-{
- nm_auto_free_checksum GChecksum *sum = NULL;
- NMDnsConfigIPData * ip_data;
-
- sum = g_checksum_new(G_CHECKSUM_SHA1);
- nm_assert(HASH_LEN == g_checksum_type_get_length(G_CHECKSUM_SHA1));
-
- if (global)
- nm_global_dns_config_update_checksum(global, sum);
- else {
- const CList *head;
-
- /* FIXME(ip-config-checksum): this relies on the fact that an IP
- * configuration without DNS parameters gives a zero checksum. */
- head = _mgr_get_ip_config_lst_head(self);
- c_list_for_each_entry (ip_data, head, ip_config_lst)
- nm_ip_config_hash(ip_data->ip_config, sum, TRUE);
- }
-
- nm_utils_checksum_get_digest_len(sum, buffer, HASH_LEN);
-}
-
static gboolean
merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf)
{
@@ -1172,19 +1139,21 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf)
}
static const char *
-get_nameserver_list(const NMIPConfig *config, NMStrBuf *tmp_strbuf)
+get_nameserver_list(int addr_family, const NML3ConfigData *l3cd, NMStrBuf *tmp_strbuf)
{
- char buf[NM_UTILS_INET_ADDRSTRLEN];
- int addr_family;
- guint num;
- guint i;
+ char buf[NM_UTILS_INET_ADDRSTRLEN];
+ guint num;
+ guint i;
+ gconstpointer nameservers;
nm_str_buf_reset(tmp_strbuf);
- addr_family = nm_ip_config_get_addr_family(config);
- num = nm_ip_config_get_num_nameservers(config);
+ nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num);
for (i = 0; i < num; i++) {
- nm_utils_inet_ntop(addr_family, nm_ip_config_get_nameserver(config, i), buf);
+ const NMIPAddr *addr;
+
+ addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i);
+ nm_utils_inet_ntop(addr_family, addr->addr_ptr, buf);
if (i > 0)
nm_str_buf_append_c(tmp_strbuf, ' ');
nm_str_buf_append(tmp_strbuf, buf);
@@ -1227,36 +1196,39 @@ _collect_resolv_conf_data(NMDnsManager * self,
merge_global_dns_config(&rc, global_config);
else {
nm_auto_str_buf NMStrBuf tmp_strbuf = NM_STR_BUF_INIT(0, FALSE);
- int prio;
int first_prio = 0;
const NMDnsConfigIPData *ip_data;
const CList * head;
gboolean is_first = TRUE;
- head = _mgr_get_ip_config_lst_head(self);
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
+ head = _mgr_get_ip_data_lst_head(self);
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
gboolean skip = FALSE;
+ int dns_priority;
_ASSERT_dns_config_ip_data(ip_data);
- prio = nm_ip_config_get_dns_priority(ip_data->ip_config);
+ if (!nm_l3_config_data_get_dns_priority(ip_data->l3cd,
+ ip_data->addr_family,
+ &dns_priority))
+ nm_assert_not_reached();
if (is_first) {
is_first = FALSE;
- first_prio = prio;
- } else if (first_prio < 0 && first_prio != prio)
+ first_prio = dns_priority;
+ } else if (first_prio < 0 && first_prio != dns_priority)
skip = TRUE;
_LOGT("config: %8d %-7s v%c %-5d %s: %s",
- prio,
+ dns_priority,
_config_type_to_string(ip_data->ip_config_type),
- nm_utils_addr_family_to_char(nm_ip_config_get_addr_family(ip_data->ip_config)),
+ nm_utils_addr_family_to_char(ip_data->addr_family),
ip_data->data->ifindex,
skip ? "<SKIP>" : "",
- get_nameserver_list(ip_data->ip_config, &tmp_strbuf));
+ get_nameserver_list(ip_data->addr_family, ip_data->l3cd, &tmp_strbuf));
if (!skip)
- merge_one_ip_config(&rc, ip_data->data->ifindex, ip_data->ip_config);
+ merge_one_l3cd(&rc, ip_data->addr_family, ip_data->data->ifindex, ip_data->l3cd);
}
}
@@ -1292,27 +1264,32 @@ _collect_resolv_conf_data(NMDnsManager * self,
/*****************************************************************************/
static char **
-get_ip_rdns_domains(NMIPConfig *ip_config)
+get_ip_rdns_domains(int addr_family, const NML3ConfigData *l3cd)
{
- int addr_family = nm_ip_config_get_addr_family(ip_config);
- char ** strv;
- GPtrArray * domains;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIPAddress *address;
- const NMPlatformIPRoute * route;
-
- nm_assert_addr_family(addr_family);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ char ** strv;
+ GPtrArray * domains;
+ NMDedupMultiIter ipconf_iter;
+ const NMPObject *obj;
domains = g_ptr_array_sized_new(5);
- nm_ip_config_iter_ip_address_for_each (&ipconf_iter, ip_config, &address) {
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &obj,
+ NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) {
nm_utils_get_reverse_dns_domains_ip(addr_family,
- address->address_ptr,
- address->plen,
+ NMP_OBJECT_CAST_IP_ADDRESS(obj)->address_ptr,
+ NMP_OBJECT_CAST_IP_ADDRESS(obj)->plen,
domains);
}
- nm_ip_config_iter_ip_route_for_each (&ipconf_iter, ip_config, &route) {
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &obj,
+ NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) {
+ const NMPlatformIPRoute *route = NMP_OBJECT_CAST_IP_ROUTE(obj);
+
if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) {
nm_utils_get_reverse_dns_domains_ip(addr_family,
route->network_ptr,
@@ -1394,12 +1371,12 @@ _mgr_configs_data_construct(NMDnsManager *self)
CList * head;
int prev_priority = G_MININT;
- head = _mgr_get_ip_config_lst_head(self);
+ head = _mgr_get_ip_data_lst_head(self);
#if NM_MORE_ASSERTS
/* we call _mgr_configs_data_clear() at the end of update. We
* don't expect any domain settings here. */
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
nm_assert(!ip_data->domains.search);
nm_assert(!ip_data->domains.reverse);
nm_assert(!ip_data->domains.has_default_route_explicit);
@@ -1408,15 +1385,17 @@ _mgr_configs_data_construct(NMDnsManager *self)
}
#endif
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
- NMIPConfig *ip_config = ip_data->ip_config;
- gboolean add_wildcard = FALSE;
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
+ gboolean add_wildcard = FALSE;
+ guint num;
- if (!nm_ip_config_get_num_nameservers(ip_config))
+ nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
+ if (num == 0)
continue;
- if (nm_ip_config_best_default_route_get(ip_config))
+ if (nm_l3_config_data_get_best_default_route(ip_data->l3cd, ip_data->addr_family)) {
+ /* FIXME(l3cfg): the best-default route of a l3cd is not significant! */
add_wildcard = TRUE;
- else {
+ } else {
/* If a VPN has never-default=no but doesn't get a default
* route (this can happen for example when the server
* pushes routes with openconnect), and there are no
@@ -1424,9 +1403,10 @@ _mgr_configs_data_construct(NMDnsManager *self)
* by the server would be unused. It is preferable in this
* case to use the VPN DNS server for all queries. */
if (ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN
- && !nm_ip_config_get_never_default(ip_data->ip_config)
- && nm_ip_config_get_num_searches(ip_data->ip_config) == 0
- && nm_ip_config_get_num_domains(ip_data->ip_config) == 0)
+ && nm_l3_config_data_get_never_default(ip_data->l3cd, ip_data->addr_family)
+ == NM_TERNARY_FALSE
+ && !nm_l3_config_data_get_searches(ip_data->l3cd, ip_data->addr_family, NULL)
+ && !nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, NULL))
add_wildcard = TRUE;
}
@@ -1437,29 +1417,33 @@ _mgr_configs_data_construct(NMDnsManager *self)
}
}
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
- NMIPConfig * ip_config = ip_data->ip_config;
- int priority;
- const char **domains;
- guint n_searches;
- guint n_domains;
- guint num_dom1;
- guint num_dom2;
- guint n_domains_allocated;
- guint i;
- gboolean has_default_route_maybe = FALSE;
- gboolean has_default_route_explicit = FALSE;
- gboolean has_default_route_auto = FALSE;
-
- if (!nm_ip_config_get_num_nameservers(ip_config))
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
+ int priority;
+ const char ** domains;
+ const char *const *strv_searches;
+ const char *const *strv_domains;
+ guint n_searches;
+ guint n_domains;
+ guint num_dom1;
+ guint num_dom2;
+ guint n_domains_allocated;
+ guint i;
+ gboolean has_default_route_maybe = FALSE;
+ gboolean has_default_route_explicit = FALSE;
+ gboolean has_default_route_auto = FALSE;
+ guint num;
+
+ nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
+ if (num == 0)
continue;
- n_searches = nm_ip_config_get_num_searches(ip_config);
- n_domains = nm_ip_config_get_num_domains(ip_config);
+ strv_searches =
+ nm_l3_config_data_get_searches(ip_data->l3cd, ip_data->addr_family, &n_searches);
+ strv_domains =
+ nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, &n_domains);
- priority = nm_ip_config_get_dns_priority(ip_config);
+ priority = _dns_config_ip_data_get_dns_priority(ip_data);
- nm_assert(priority != 0);
nm_assert(prev_priority <= priority);
prev_priority = priority;
@@ -1487,10 +1471,10 @@ _mgr_configs_data_construct(NMDnsManager *self)
/* searches are preferred over domains */
if (n_searches > 0) {
for (i = 0; i < n_searches; i++)
- domains[num_dom1++] = nm_ip_config_get_search(ip_config, i);
+ domains[num_dom1++] = strv_searches[i];
} else {
for (i = 0; i < n_domains; i++)
- domains[num_dom1++] = nm_ip_config_get_domain(ip_config, i);
+ domains[num_dom1++] = strv_domains[i];
}
nm_assert(num_dom1 < n_domains_allocated);
@@ -1578,8 +1562,8 @@ _mgr_configs_data_construct(NMDnsManager *self)
nm_assert(!ip_data->domains.search);
nm_assert(!ip_data->domains.reverse);
- ip_data->domains.search = domains;
- ip_data->domains.reverse = get_ip_rdns_domains(ip_config);
+ ip_data->domains.search = domains;
+ ip_data->domains.reverse = get_ip_rdns_domains(ip_data->addr_family, ip_data->l3cd);
ip_data->domains.has_default_route_explicit = has_default_route_explicit;
ip_data->domains.has_default_route_exclusive =
has_default_route_explicit || (priority < 0 && has_default_route_auto);
@@ -1611,8 +1595,8 @@ _mgr_configs_data_clear(NMDnsManager *self)
NMDnsConfigIPData *ip_data;
CList * head;
- head = _mgr_get_ip_config_lst_head(self);
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
+ head = _mgr_get_ip_data_lst_head(self);
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
nm_clear_g_free(&ip_data->domains.search);
nm_clear_pointer(&ip_data->domains.reverse, g_strfreev);
ip_data->domains.has_default_route_explicit = FALSE;
@@ -1643,6 +1627,8 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError
nm_assert(!error || !*error);
+ priv->config_changed = FALSE;
+
if (priv->is_stopped) {
_LOGD("update-dns: not updating resolv.conf (is stopped)");
return TRUE;
@@ -1663,9 +1649,6 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError
data = nm_config_get_data(priv->config);
global_config = nm_config_data_get_global_dns_config(data);
- /* Update hash with config we're applying */
- compute_hash(self, global_config, priv->hash);
-
_collect_resolv_conf_data(self,
global_config,
&searches,
@@ -1680,7 +1663,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError
if (priv->sd_resolve_plugin) {
nm_dns_plugin_update(priv->sd_resolve_plugin,
global_config,
- _mgr_get_ip_config_lst_head(self),
+ _mgr_get_ip_data_lst_head(self),
priv->hostname,
NULL);
}
@@ -1702,7 +1685,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError
_LOGD("update-dns: updating plugin %s", plugin_name);
if (!nm_dns_plugin_update(plugin,
global_config,
- _mgr_get_ip_config_lst_head(self),
+ _mgr_get_ip_data_lst_head(self),
priv->hostname,
&plugin_error)) {
_LOGW("update-dns: plugin %s update failed: %s", plugin_name, plugin_error->message);
@@ -1834,53 +1817,101 @@ plugin_skip:;
/*****************************************************************************/
-static void
-_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigIPData *ip_data)
-{
- _ASSERT_dns_config_ip_data(ip_data);
-
- NM_DNS_MANAGER_GET_PRIVATE(ip_data->data->self)->ip_config_lst_need_sort = TRUE;
-}
-
gboolean
-nm_dns_manager_set_ip_config(NMDnsManager * self,
- NMIPConfig * ip_config,
- NMDnsIPConfigType ip_config_type)
+nm_dns_manager_set_ip_config(NMDnsManager * self,
+ int addr_family,
+ gconstpointer source_tag,
+ const NML3ConfigData *l3cd,
+ NMDnsIPConfigType ip_config_type,
+ gboolean replace_all)
{
NMDnsManagerPrivate *priv;
- NMDnsConfigIPData * ip_data;
NMDnsConfigData * data;
int ifindex;
+ gboolean changed = FALSE;
+ NMDnsConfigIPData * ip_data = NULL;
+ int dns_priority;
g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE);
- g_return_val_if_fail(NM_IS_IP_CONFIG(ip_config), FALSE);
+ g_return_val_if_fail(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd), FALSE);
+ g_return_val_if_fail(source_tag, FALSE);
+
+ if (addr_family == AF_UNSPEC) {
+ /* Setting AF_UNSPEC is a shortcut for calling this function twice for AF_INET and
+ * AF_INET6. */
+ if (nm_dns_manager_set_ip_config(self,
+ AF_INET,
+ source_tag,
+ l3cd,
+ ip_config_type,
+ replace_all))
+ changed = TRUE;
+ if (nm_dns_manager_set_ip_config(self,
+ AF_INET6,
+ source_tag,
+ l3cd,
+ ip_config_type,
+ replace_all))
+ changed = TRUE;
+ return changed;
+ }
- ifindex = nm_ip_config_get_ifindex(ip_config);
- g_return_val_if_fail(ifindex > 0, FALSE);
+ nm_assert_addr_family(addr_family);
priv = NM_DNS_MANAGER_GET_PRIVATE(self);
- data = g_hash_table_lookup(priv->configs_dict, &ifindex);
- if (!data)
- ip_data = NULL;
- else
- ip_data = _dns_config_data_find_ip_config(data, ip_config);
+ data = NULL;
+ if (l3cd) {
+ ifindex = nm_l3_config_data_get_ifindex(l3cd);
+ nm_assert(ifindex > 0);
+ data = g_hash_table_lookup(priv->configs_dict, &ifindex);
+ }
- if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED) {
- if (!ip_data)
- return FALSE;
- /* deleting a config doesn't invalidate the configs' sort order. */
- _dns_config_ip_data_free(ip_data);
- if (c_list_is_empty(&data->data_lst_head))
- g_hash_table_remove(priv->configs_dict, &ifindex);
- goto changed;
+ if (data) {
+ NMDnsConfigIPData *ip_data_iter;
+ NMDnsConfigIPData *ip_data_safe;
+
+ c_list_for_each_entry_safe (ip_data_iter, ip_data_safe, &data->data_lst_head, data_lst) {
+ _ASSERT_dns_config_ip_data(ip_data_iter);
+
+ if (ip_data_iter->source_tag != source_tag)
+ continue;
+ if (ip_data_iter->addr_family != addr_family)
+ continue;
+
+ if (ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED && ip_data_iter->l3cd == l3cd) {
+ nm_assert(!ip_data);
+ ip_data = ip_data_iter;
+ continue;
+ }
+
+ if (!replace_all && l3cd && ip_data_iter->l3cd != l3cd)
+ continue;
+
+ changed = TRUE;
+ _dns_config_ip_data_free(ip_data_iter);
+ }
}
+ if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED)
+ goto done;
+
+ if (!l3cd)
+ goto done;
+
if (ip_data && ip_data->ip_config_type == ip_config_type) {
/* nothing to do. */
- return FALSE;
+ goto done;
}
+ dns_priority = _dns_config_ip_data_get_dns_priority1(l3cd, addr_family);
+ if (dns_priority == 0) {
+ /* no DNS priority for this address family. Skip it! */
+ goto done;
+ }
+
+ changed = TRUE;
+
if (!data) {
data = g_slice_new(NMDnsConfigData);
*data = (NMDnsConfigData){
@@ -1895,13 +1926,28 @@ nm_dns_manager_set_ip_config(NMDnsManager * self,
}
if (!ip_data)
- ip_data = _dns_config_ip_data_new(data, ip_config, ip_config_type);
+ ip_data = _dns_config_ip_data_new(data, addr_family, source_tag, l3cd, ip_config_type);
else
ip_data->ip_config_type = ip_config_type;
- priv->ip_config_lst_need_sort = TRUE;
+ priv->ip_data_lst_need_sort = TRUE;
+
+ nm_assert(l3cd);
+ nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED);
+ nm_assert(ip_data->addr_family == addr_family);
+ nm_assert(ip_data->source_tag == source_tag);
+ nm_assert(ip_data->l3cd == l3cd);
+ nm_assert(ip_data->ip_config_type == ip_config_type);
+
+done:
+ if (!changed)
+ return FALSE;
+
+ priv->config_changed = TRUE;
+
+ if (data && c_list_is_empty(&data->data_lst_head))
+ g_hash_table_remove(priv->configs_dict, data);
-changed:
if (!priv->updates_queue) {
gs_free_error GError *error = NULL;
@@ -1957,11 +2003,8 @@ nm_dns_manager_begin_updates(NMDnsManager *self, const char *func)
NMDnsManagerPrivate *priv;
g_return_if_fail(self != NULL);
- priv = NM_DNS_MANAGER_GET_PRIVATE(self);
- /* Save current hash when starting a new batch */
- if (priv->updates_queue == 0)
- memcpy(priv->prev_hash, priv->hash, sizeof(priv->hash));
+ priv = NM_DNS_MANAGER_GET_PRIVATE(self);
priv->updates_queue++;
@@ -1973,20 +2016,16 @@ nm_dns_manager_end_updates(NMDnsManager *self, const char *func)
{
NMDnsManagerPrivate *priv;
gs_free_error GError *error = NULL;
- gboolean changed;
- guint8 new[HASH_LEN];
g_return_if_fail(self != NULL);
priv = NM_DNS_MANAGER_GET_PRIVATE(self);
g_return_if_fail(priv->updates_queue > 0);
- compute_hash(self, nm_config_data_get_global_dns_config(nm_config_get_data(priv->config)), new);
- changed = (memcmp(new, priv->prev_hash, sizeof(new)) != 0) ? TRUE : FALSE;
- _LOGD("(%s): DNS configuration %s", func, changed ? "changed" : "did not change");
+ _LOGD("(%s): DNS configuration %s", func, priv->config_changed ? "changed" : "did not change");
priv->updates_queue--;
- if ((priv->updates_queue > 0) || (changed == FALSE)) {
+ if ((priv->updates_queue > 0) || !priv->config_changed) {
_LOGD("(%s): no DNS changes to commit (%d)", func, priv->updates_queue);
return;
}
@@ -1995,8 +2034,6 @@ nm_dns_manager_end_updates(NMDnsManager *self, const char *func)
_LOGD("(%s): committing DNS changes (%d)", func, priv->updates_queue);
if (!update_dns(self, FALSE, FALSE, &error))
_LOGW("could not commit DNS changes: %s", error->message);
-
- memset(priv->prev_hash, 0, sizeof(priv->prev_hash));
}
void
@@ -2319,6 +2356,8 @@ config_changed_cb(NMConfig * config,
NMConfigData * old_data,
NMDnsManager * self)
{
+ NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self);
+
if (NM_FLAGS_ANY(changes,
NM_CONFIG_CHANGE_DNS_MODE | NM_CONFIG_CHANGE_RC_MANAGER
| NM_CONFIG_CHANGE_CAUSE_SIGHUP | NM_CONFIG_CHANGE_CAUSE_DNS_FULL)) {
@@ -2338,6 +2377,7 @@ config_changed_cb(NMConfig * config,
| NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) {
gs_free_error GError *error = NULL;
+ priv->config_changed = TRUE;
if (!update_dns(self, FALSE, TRUE, &error))
_LOGW("could not commit DNS changes: %s", error->message);
}
@@ -2415,51 +2455,54 @@ _get_config_variant(NMDnsManager *self)
g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
- head = _mgr_get_ip_config_lst_head(self);
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
- const NMIPConfig *ip_config = ip_data->ip_config;
- GVariantBuilder entry_builder;
- GVariantBuilder strv_builder;
- guint i, num;
- const int addr_family = nm_ip_config_get_addr_family(ip_config);
- char buf[NM_UTILS_INET_ADDRSTRLEN];
- const NMIPAddr * addr;
- const char * ifname;
-
- num = nm_ip_config_get_num_nameservers(ip_config);
- if (!num)
+ head = _mgr_get_ip_data_lst_head(self);
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
+ GVariantBuilder entry_builder;
+ GVariantBuilder strv_builder;
+ guint num;
+ guint num_domains;
+ guint num_searches;
+ guint i;
+ char buf[NM_UTILS_INET_ADDRSTRLEN];
+ const char * ifname;
+ gconstpointer nameservers;
+
+ nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
+ if (num == 0)
continue;
g_variant_builder_init(&entry_builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_init(&strv_builder, G_VARIANT_TYPE("as"));
for (i = 0; i < num; i++) {
- addr = nm_ip_config_get_nameserver(ip_config, i);
- g_variant_builder_add(&strv_builder, "s", nm_utils_inet_ntop(addr_family, addr, buf));
+ const NMIPAddr *addr;
+
+ addr = nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i);
+ g_variant_builder_add(&strv_builder,
+ "s",
+ nm_utils_inet_ntop(ip_data->addr_family, addr, buf));
}
g_variant_builder_add(&entry_builder,
"{sv}",
"nameservers",
g_variant_builder_end(&strv_builder));
- num = nm_ip_config_get_num_domains(ip_config);
- num += nm_ip_config_get_num_searches(ip_config);
+ nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, &num_domains);
+ nm_l3_config_data_get_searches(ip_data->l3cd, ip_data->addr_family, &num_searches);
+ num = num_domains + num_searches;
if (num > 0) {
if (!array_domains)
array_domains = g_ptr_array_sized_new(num);
else
g_ptr_array_set_size(array_domains, 0);
- add_dns_domains(array_domains, ip_config, TRUE, FALSE);
+ add_dns_domains(array_domains, ip_data->addr_family, ip_data->l3cd, TRUE, FALSE);
if (array_domains->len) {
- g_variant_builder_init(&strv_builder, G_VARIANT_TYPE("as"));
- for (i = 0; i < array_domains->len; i++) {
- g_variant_builder_add(&strv_builder, "s", array_domains->pdata[i]);
- }
g_variant_builder_add(&entry_builder,
"{sv}",
"domains",
- g_variant_builder_end(&strv_builder));
+ g_variant_new_strv((const char *const *) array_domains->pdata,
+ array_domains->len));
}
}
@@ -2474,7 +2517,7 @@ _get_config_variant(NMDnsManager *self)
g_variant_builder_add(&entry_builder,
"{sv}",
"priority",
- g_variant_new_int32(nm_ip_config_get_dns_priority(ip_config)));
+ g_variant_new_int32(_dns_config_ip_data_get_dns_priority(ip_data)));
g_variant_builder_add(
&entry_builder,
@@ -2521,7 +2564,7 @@ nm_dns_manager_init(NMDnsManager *self)
_LOGT("creating...");
c_list_init(&priv->configs_lst_head);
- c_list_init(&priv->ip_config_lst_head);
+ c_list_init(&priv->ip_data_lst_head);
priv->config = g_object_ref(nm_config_get());
@@ -2531,9 +2574,6 @@ nm_dns_manager_init(NMDnsManager *self)
(GDestroyNotify) _dns_config_data_free,
NULL);
- /* Set the initial hash */
- compute_hash(self, NULL, NM_DNS_MANAGER_GET_PRIVATE(self)->hash);
-
g_signal_connect(G_OBJECT(priv->config),
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
G_CALLBACK(config_changed_cb),
@@ -2559,7 +2599,7 @@ dispose(GObject *object)
g_clear_object(&priv->sd_resolve_plugin);
_clear_plugin(self);
- c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_config_lst_head, ip_config_lst)
+ c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_data_lst_head, ip_data_lst)
_dns_config_ip_data_free(ip_data);
nm_clear_pointer(&priv->configs_dict, g_hash_table_destroy);
diff --git a/src/core/dns/nm-dns-manager.h b/src/core/dns/nm-dns-manager.h
index 1972a5dd7a..2b5ca634b1 100644
--- a/src/core/dns/nm-dns-manager.h
+++ b/src/core/dns/nm-dns-manager.h
@@ -8,8 +8,7 @@
#ifndef __NETWORKMANAGER_DNS_MANAGER_H__
#define __NETWORKMANAGER_DNS_MANAGER_H__
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "c-list/src/c-list.h"
#include "nm-setting-connection.h"
#include "nm-dns-plugin.h"
@@ -28,10 +27,12 @@ struct _NMDnsManager;
typedef struct {
struct _NMDnsConfigData *data;
- NMIPConfig * ip_config;
+ gconstpointer source_tag;
+ const NML3ConfigData * l3cd;
CList data_lst;
- CList ip_config_lst;
+ CList ip_data_lst;
NMDnsIPConfigType ip_config_type;
+ int addr_family;
struct {
const char **search;
char ** reverse;
@@ -97,9 +98,12 @@ NMDnsManager *nm_dns_manager_get(void);
void nm_dns_manager_begin_updates(NMDnsManager *self, const char *func);
void nm_dns_manager_end_updates(NMDnsManager *self, const char *func);
-gboolean nm_dns_manager_set_ip_config(NMDnsManager * self,
- NMIPConfig * ip_config,
- NMDnsIPConfigType ip_config_type);
+gboolean nm_dns_manager_set_ip_config(NMDnsManager * self,
+ int addr_family,
+ gconstpointer source_tag,
+ const NML3ConfigData *l3cd,
+ NMDnsIPConfigType ip_config_type,
+ gboolean replace_all);
void nm_dns_manager_set_initial_hostname(NMDnsManager *self, const char *hostname);
void nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean skip_update);
diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c
index 5d2eff0be2..8d91bd246e 100644
--- a/src/core/dns/nm-dns-systemd-resolved.c
+++ b/src/core/dns/nm-dns-systemd-resolved.c
@@ -21,10 +21,9 @@
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-platform/nm-platform.h"
#include "nm-utils.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "nm-dbus-manager.h"
#include "nm-manager.h"
+#include "nm-l3-config-data.h"
#include "nm-setting-connection.h"
#include "devices/nm-device.h"
#include "NetworkManagerUtils.h"
@@ -230,40 +229,42 @@ static gboolean
update_add_ip_config(NMDnsSystemdResolved *self,
GVariantBuilder * dns,
GVariantBuilder * domains,
- NMDnsConfigIPData * data)
+ NMDnsConfigIPData * ip_data)
{
- int addr_family;
- gsize addr_size;
- guint i, n;
- gboolean is_routing;
- const char *domain;
- gboolean has_config = FALSE;
-
- addr_family = nm_ip_config_get_addr_family(data->ip_config);
- addr_size = nm_utils_addr_family_to_size(addr_family);
-
- if ((!data->domains.search || !data->domains.search[0])
- && !data->domains.has_default_route_exclusive && !data->domains.has_default_route)
+ gsize addr_size;
+ guint n;
+ guint i;
+ gboolean is_routing;
+ const char * domain;
+ gboolean has_config = FALSE;
+ gconstpointer nameservers;
+
+ addr_size = nm_utils_addr_family_to_size(ip_data->addr_family);
+
+ if ((!ip_data->domains.search || !ip_data->domains.search[0])
+ && !ip_data->domains.has_default_route_exclusive && !ip_data->domains.has_default_route)
return FALSE;
- n = nm_ip_config_get_num_nameservers(data->ip_config);
+ nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &n);
for (i = 0; i < n; i++) {
g_variant_builder_open(dns, G_VARIANT_TYPE("(iay)"));
- g_variant_builder_add(dns, "i", addr_family);
+ g_variant_builder_add(dns, "i", ip_data->addr_family);
g_variant_builder_add_value(
dns,
- nm_g_variant_new_ay(nm_ip_config_get_nameserver(data->ip_config, i), addr_size));
+ nm_g_variant_new_ay(nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i),
+ addr_size));
g_variant_builder_close(dns);
has_config = TRUE;
}
- if (!data->domains.has_default_route_explicit && data->domains.has_default_route_exclusive) {
+ if (!ip_data->domains.has_default_route_explicit
+ && ip_data->domains.has_default_route_exclusive) {
g_variant_builder_add(domains, "(sb)", ".", TRUE);
has_config = TRUE;
}
- if (data->domains.search) {
- for (i = 0; data->domains.search[i]; i++) {
- domain = nm_utils_parse_dns_domain(data->domains.search[i], &is_routing);
+ if (ip_data->domains.search) {
+ for (i = 0; ip_data->domains.search[i]; i++) {
+ domain = nm_utils_parse_dns_domain(ip_data->domains.search[i], &is_routing);
g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing);
has_config = TRUE;
}
@@ -304,17 +305,16 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic)
g_variant_builder_open(&domains, G_VARIANT_TYPE("a(sb)"));
c_list_for_each_entry (elem, &ic->configs_lst_head, lst) {
- NMDnsConfigIPData *data = elem->data;
- NMIPConfig * ip_config = data->ip_config;
+ NMDnsConfigIPData *ip_data = elem->data;
- has_config |= update_add_ip_config(self, &dns, &domains, data);
+ has_config |= update_add_ip_config(self, &dns, &domains, ip_data);
- if (data->domains.has_default_route)
+ if (ip_data->domains.has_default_route)
has_default_route = TRUE;
- if (NM_IS_IP4_CONFIG(ip_config)) {
- mdns = NM_MAX(mdns, nm_ip4_config_mdns_get(NM_IP4_CONFIG(ip_config)));
- llmnr = NM_MAX(llmnr, nm_ip4_config_llmnr_get(NM_IP4_CONFIG(ip_config)));
+ if (NM_IS_IPv4(ip_data->addr_family)) {
+ mdns = NM_MAX(mdns, nm_l3_config_data_get_mdns(ip_data->l3cd));
+ llmnr = NM_MAX(llmnr, nm_l3_config_data_get_llmnr(ip_data->l3cd));
}
}
@@ -508,7 +508,7 @@ start_resolve:
static gboolean
update(NMDnsPlugin * plugin,
const NMGlobalDnsConfig *global_config,
- const CList * ip_config_lst_head,
+ const CList * ip_data_lst_head,
const char * hostname,
GError ** error)
{
@@ -526,11 +526,11 @@ update(NMDnsPlugin * plugin,
interfaces =
g_hash_table_new_full(nm_direct_hash, NULL, NULL, (GDestroyNotify) _interface_config_free);
- c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) {
+ c_list_for_each_entry (ip_data, ip_data_lst_head, ip_data_lst) {
InterfaceConfig *ic = NULL;
ifindex = ip_data->data->ifindex;
- nm_assert(ifindex == nm_ip_config_get_ifindex(ip_data->ip_config));
+ nm_assert(ifindex == nm_l3_config_data_get_ifindex(ip_data->l3cd));
ic = g_hash_table_lookup(interfaces, GINT_TO_POINTER(ifindex));
if (!ic) {
diff --git a/src/core/dnsmasq/nm-dnsmasq-manager.c b/src/core/dnsmasq/nm-dnsmasq-manager.c
index e8697e817e..f4eea33a13 100644
--- a/src/core/dnsmasq/nm-dnsmasq-manager.c
+++ b/src/core/dnsmasq/nm-dnsmasq-manager.c
@@ -17,6 +17,7 @@
#include "nm-dnsmasq-utils.h"
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
+#include "nm-l3-config-data.h"
#include "libnm-core-intern/nm-core-internal.h"
#define CONFDIR NMCONFDIR "/dnsmasq-shared.d"
@@ -85,24 +86,28 @@ dm_watch_cb(GPid pid, int status, gpointer user_data)
}
static GPtrArray *
-create_dm_cmd_line(const char * iface,
- const NMIP4Config *ip4_config,
- const char * pidfile,
- gboolean announce_android_metered,
- GError ** error)
+create_dm_cmd_line(const char * iface,
+ const NML3ConfigData *l3cd,
+ const char * pidfile,
+ gboolean announce_android_metered,
+ GError ** error)
{
gs_unref_ptrarray GPtrArray *cmd = NULL;
nm_auto_free_gstring GString *s = NULL;
char first[INET_ADDRSTRLEN];
char last[INET_ADDRSTRLEN];
char listen_address_s[INET_ADDRSTRLEN];
- char tmpaddr[INET_ADDRSTRLEN];
+ char sbuf_addr[INET_ADDRSTRLEN];
gs_free char * error_desc = NULL;
const char * dm_binary;
const NMPlatformIP4Address * listen_address;
- guint i, n;
+ const in_addr_t * ipv4arr;
+ const char *const * strarr;
+ guint n;
+ guint i;
- listen_address = nm_ip4_config_get_first_address(ip4_config);
+ listen_address = NMP_OBJECT_CAST_IP4_ADDRESS(
+ nm_l3_config_data_get_first_obj(l3cd, NMP_OBJECT_TYPE_IP4_ADDRESS, NULL));
g_return_val_if_fail(listen_address, NULL);
@@ -151,28 +156,28 @@ create_dm_cmd_line(const char * iface,
nm_strv_ptrarray_add_string_printf(cmd, "--dhcp-range=%s,%s,60m", first, last);
- if (nm_ip4_config_best_default_route_get(ip4_config)) {
+ if (nm_l3_config_data_get_best_default_route(l3cd, AF_INET)) {
nm_strv_ptrarray_add_string_concat(cmd, "--dhcp-option=option:router,", listen_address_s);
}
- if ((n = nm_ip4_config_get_num_nameservers(ip4_config))) {
+ ipv4arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &n);
+ if (n > 0) {
nm_gstring_prepare(&s);
g_string_append(s, "--dhcp-option=option:dns-server");
for (i = 0; i < n; i++) {
g_string_append_c(s, ',');
- g_string_append(
- s,
- _nm_utils_inet4_ntop(nm_ip4_config_get_nameserver(ip4_config, i), tmpaddr));
+ g_string_append(s, _nm_utils_inet4_ntop(ipv4arr[i], sbuf_addr));
}
nm_strv_ptrarray_take_gstring(cmd, &s);
}
- if ((n = nm_ip4_config_get_num_searches(ip4_config))) {
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &n);
+ if (n > 0) {
nm_gstring_prepare(&s);
g_string_append(s, "--dhcp-option=option:domain-search");
for (i = 0; i < n; i++) {
g_string_append_c(s, ',');
- g_string_append(s, nm_ip4_config_get_search(ip4_config, i));
+ g_string_append(s, strarr[i]);
}
nm_strv_ptrarray_take_gstring(cmd, &s);
}
@@ -237,25 +242,25 @@ out:
}
gboolean
-nm_dnsmasq_manager_start(NMDnsMasqManager *manager,
- NMIP4Config * ip4_config,
- gboolean announce_android_metered,
- GError ** error)
+nm_dnsmasq_manager_start(NMDnsMasqManager * manager,
+ const NML3ConfigData *l3cd,
+ gboolean announce_android_metered,
+ GError ** error)
{
- NMDnsMasqManagerPrivate *priv;
gs_unref_ptrarray GPtrArray *dm_cmd = NULL;
gs_free char * cmd_str = NULL;
+ NMDnsMasqManagerPrivate * priv;
g_return_val_if_fail(NM_IS_DNSMASQ_MANAGER(manager), FALSE);
g_return_val_if_fail(!error || !*error, FALSE);
- g_return_val_if_fail(nm_ip4_config_get_num_addresses(ip4_config) > 0, FALSE);
+ g_return_val_if_fail(NM_IS_L3_CONFIG_DATA(l3cd), FALSE);
+ g_return_val_if_fail(nm_l3_config_data_get_num_addresses(l3cd, AF_INET) > 0, FALSE);
priv = NM_DNSMASQ_MANAGER_GET_PRIVATE(manager);
kill_existing_by_pidfile(priv->pidfile);
- dm_cmd =
- create_dm_cmd_line(priv->iface, ip4_config, priv->pidfile, announce_android_metered, error);
+ dm_cmd = create_dm_cmd_line(priv->iface, l3cd, priv->pidfile, announce_android_metered, error);
if (!dm_cmd)
return FALSE;
diff --git a/src/core/dnsmasq/nm-dnsmasq-manager.h b/src/core/dnsmasq/nm-dnsmasq-manager.h
index 272d1cead1..78ca37251e 100644
--- a/src/core/dnsmasq/nm-dnsmasq-manager.h
+++ b/src/core/dnsmasq/nm-dnsmasq-manager.h
@@ -6,8 +6,6 @@
#ifndef __NETWORKMANAGER_DNSMASQ_MANAGER_H__
#define __NETWORKMANAGER_DNSMASQ_MANAGER_H__
-#include "nm-ip4-config.h"
-
#define NM_TYPE_DNSMASQ_MANAGER (nm_dnsmasq_manager_get_type())
#define NM_DNSMASQ_MANAGER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManager))
@@ -35,10 +33,10 @@ GType nm_dnsmasq_manager_get_type(void);
NMDnsMasqManager *nm_dnsmasq_manager_new(const char *iface);
-gboolean nm_dnsmasq_manager_start(NMDnsMasqManager *manager,
- NMIP4Config * ip4_config,
- gboolean announce_android_metered,
- GError ** error);
+gboolean nm_dnsmasq_manager_start(NMDnsMasqManager * manager,
+ const NML3ConfigData *l3cd,
+ gboolean announce_android_metered,
+ GError ** error);
void nm_dnsmasq_manager_stop(NMDnsMasqManager *manager);
diff --git a/src/core/meson.build b/src/core/meson.build
index 46b636817d..aeda6c25d3 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -54,8 +54,6 @@ libNetworkManagerBase = static_library(
'nm-l3-ipv6ll.c',
'nm-l3cfg.c',
'nm-ip-config.c',
- 'nm-ip4-config.c',
- 'nm-ip6-config.c',
),
dependencies: [
core_default_dep,
@@ -93,7 +91,6 @@ endif
libNetworkManager = static_library(
'NetworkManager',
sources: files(
- 'devices/nm-acd-manager.c',
'devices/nm-device-6lowpan.c',
'devices/nm-device-bond.c',
'devices/nm-device-bridge.c',
@@ -169,7 +166,6 @@ libNetworkManager = static_library(
'nm-manager.c',
'nm-pacrunner-manager.c',
'nm-policy.c',
- 'nm-proxy-config.c',
'nm-rfkill-manager.c',
'nm-session-monitor.c',
'nm-sleep-monitor.c',
diff --git a/src/core/ndisc/nm-fake-ndisc.c b/src/core/ndisc/nm-fake-ndisc.c
index ffe07ab6b7..2794e286da 100644
--- a/src/core/ndisc/nm-fake-ndisc.c
+++ b/src/core/ndisc/nm-fake-ndisc.c
@@ -10,6 +10,7 @@
#include <arpa/inet.h>
#include "nm-ndisc-private.h"
+#include "nm-l3cfg.h"
#define _NMLOG_PREFIX_NAME "ndisc-fake"
@@ -354,28 +355,23 @@ nm_fake_ndisc_init(NMFakeNDisc *fake_ndisc)
{}
NMNDisc *
-nm_fake_ndisc_new(int ifindex, const char *ifname)
+nm_fake_ndisc_new(NML3Cfg *l3cfg)
{
- return g_object_new(NM_TYPE_FAKE_NDISC,
- NM_NDISC_IFINDEX,
- ifindex,
- NM_NDISC_IFNAME,
- ifname,
- NM_NDISC_NODE_TYPE,
- (int) NM_NDISC_NODE_TYPE_HOST,
- NM_NDISC_STABLE_TYPE,
- (int) NM_UTILS_STABLE_TYPE_UUID,
- NM_NDISC_NETWORK_ID,
- "fake",
- NM_NDISC_MAX_ADDRESSES,
- NM_NDISC_MAX_ADDRESSES_DEFAULT,
- NM_NDISC_ROUTER_SOLICITATIONS,
- NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT,
- NM_NDISC_ROUTER_SOLICITATION_INTERVAL,
- NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL,
- NM_NDISC_RA_TIMEOUT,
- 30u,
- NULL);
+ const NMNDiscConfig config = {
+ .l3cfg = g_object_ref(NM_L3CFG(l3cfg)),
+ .ifname = nm_l3cfg_get_ifname(l3cfg, TRUE),
+ .node_type = NM_NDISC_NODE_TYPE_HOST,
+ .stable_type = NM_UTILS_STABLE_TYPE_UUID,
+ .network_id = "fake",
+ .max_addresses = NM_NDISC_MAX_ADDRESSES_DEFAULT,
+ .router_solicitations = NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT,
+ .router_solicitation_interval = NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL,
+ .ra_timeout = 30u,
+ .addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
+ .ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
+ };
+
+ return g_object_new(NM_TYPE_FAKE_NDISC, NM_NDISC_CONFIG, &config, NULL);
}
static void
diff --git a/src/core/ndisc/nm-fake-ndisc.h b/src/core/ndisc/nm-fake-ndisc.h
index 677f15fcac..ba0a7acb78 100644
--- a/src/core/ndisc/nm-fake-ndisc.h
+++ b/src/core/ndisc/nm-fake-ndisc.h
@@ -24,7 +24,7 @@ typedef struct _NMFakeRNDiscClass NMFakeNDiscClass;
GType nm_fake_ndisc_get_type(void);
-NMNDisc *nm_fake_ndisc_new(int ifindex, const char *ifname);
+NMNDisc *nm_fake_ndisc_new(NML3Cfg *l3cfg);
guint nm_fake_ndisc_add_ra(NMFakeNDisc * self,
guint seconds,
diff --git a/src/core/ndisc/nm-lndp-ndisc.c b/src/core/ndisc/nm-lndp-ndisc.c
index 552b0e4b59..ee040be157 100644
--- a/src/core/ndisc/nm-lndp-ndisc.c
+++ b/src/core/ndisc/nm-lndp-ndisc.c
@@ -9,16 +9,16 @@
#include <arpa/inet.h>
#include <netinet/icmp6.h>
-/* stdarg.h included because of a bug in ndp.h */
#include <stdarg.h>
#include <ndp.h>
-#include "libnm-glib-aux/nm-str-buf.h"
-#include "libnm-systemd-shared/nm-sd-utils-shared.h"
-#include "nm-ndisc-private.h"
#include "NetworkManagerUtils.h"
+#include "libnm-glib-aux/nm-str-buf.h"
#include "libnm-platform/nm-platform.h"
#include "libnm-platform/nmp-netns.h"
+#include "libnm-systemd-shared/nm-sd-utils-shared.h"
+#include "nm-l3cfg.h"
+#include "nm-ndisc-private.h"
#define _NMLOG_PREFIX_NAME "ndisc-lndp"
@@ -669,72 +669,39 @@ nm_lndp_ndisc_init(NMLndpNDisc *lndp_ndisc)
{}
NMNDisc *
-nm_lndp_ndisc_new(NMPlatform * platform,
- int ifindex,
- const char * ifname,
- NMUtilsStableType stable_type,
- const char * network_id,
- NMSettingIP6ConfigAddrGenMode addr_gen_mode,
- NMNDiscNodeType node_type,
- int max_addresses,
- int router_solicitations,
- int router_solicitation_interval,
- guint32 ra_timeout,
- GError ** error)
+nm_lndp_ndisc_new(const NMNDiscConfig *config)
{
nm_auto_pop_netns NMPNetns *netns = NULL;
- NMNDisc * ndisc;
- NMLndpNDiscPrivate * priv;
- int errsv;
+ gs_unref_object NMNDisc *ndisc = NULL;
+ NMLndpNDiscPrivate * priv;
+ int errsv;
- g_return_val_if_fail(NM_IS_PLATFORM(platform), NULL);
- g_return_val_if_fail(!error || !*error, NULL);
- g_return_val_if_fail(network_id, NULL);
+ g_return_val_if_fail(config, NULL);
+ g_return_val_if_fail(NM_IS_L3CFG(config->l3cfg), NULL);
+ g_return_val_if_fail(config->network_id, NULL);
- if (!nm_platform_netns_push(platform, &netns))
- return NULL;
+ if (!nm_platform_netns_push(nm_l3cfg_get_platform(config->l3cfg), &netns)) {
+ /* The inability to change the name space is also considered
+ * a fatal error. We have a FD open to the file descriptor, and
+ * it's unclear how to handle (or recover from) a failure to setns(). */
+ g_return_val_if_reached(NULL);
+ }
- ndisc = g_object_new(NM_TYPE_LNDP_NDISC,
- NM_NDISC_PLATFORM,
- platform,
- NM_NDISC_STABLE_TYPE,
- (int) stable_type,
- NM_NDISC_IFINDEX,
- ifindex,
- NM_NDISC_IFNAME,
- ifname,
- NM_NDISC_NETWORK_ID,
- network_id,
- NM_NDISC_ADDR_GEN_MODE,
- (int) addr_gen_mode,
- NM_NDISC_NODE_TYPE,
- (int) node_type,
- NM_NDISC_MAX_ADDRESSES,
- max_addresses,
- NM_NDISC_ROUTER_SOLICITATIONS,
- router_solicitations,
- NM_NDISC_ROUTER_SOLICITATION_INTERVAL,
- router_solicitation_interval,
- NM_NDISC_RA_TIMEOUT,
- (guint) ra_timeout,
- NULL);
+ ndisc = g_object_new(NM_TYPE_LNDP_NDISC, NM_NDISC_CONFIG, config, NULL);
priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc);
errsv = ndp_open(&priv->ndp);
if (errsv != 0) {
- errsv = nm_errno_native(errsv);
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- "failure creating libndp socket: %s (%d)",
- nm_strerror_native(errsv),
- errsv);
- g_object_unref(ndisc);
- return NULL;
+ /* This is serious. It might be ENOMEM or the inability to open (or modify)
+ * a file descriptor. In all cases there is not much reason trying to recover
+ * from that. File descriptors are a basic resource, that we just require (just
+ * like memory). */
+ g_return_val_if_reached(NULL);
}
- return ndisc;
+
+ return g_steal_pointer(&ndisc);
}
static void
@@ -754,8 +721,9 @@ nm_lndp_ndisc_class_init(NMLndpNDiscClass *klass)
NMNDiscClass *ndisc_class = NM_NDISC_CLASS(klass);
object_class->dispose = dispose;
- ndisc_class->start = start;
- ndisc_class->stop = stop;
- ndisc_class->send_rs = send_rs;
- ndisc_class->send_ra = send_ra;
+
+ ndisc_class->start = start;
+ ndisc_class->stop = stop;
+ ndisc_class->send_rs = send_rs;
+ ndisc_class->send_ra = send_ra;
}
diff --git a/src/core/ndisc/nm-lndp-ndisc.h b/src/core/ndisc/nm-lndp-ndisc.h
index 151f4bf7ae..711a95e177 100644
--- a/src/core/ndisc/nm-lndp-ndisc.h
+++ b/src/core/ndisc/nm-lndp-ndisc.h
@@ -23,17 +23,6 @@ typedef struct _NMLndpNDiscClass NMLndpNDiscClass;
GType nm_lndp_ndisc_get_type(void);
-NMNDisc *nm_lndp_ndisc_new(NMPlatform * platform,
- int ifindex,
- const char * ifname,
- NMUtilsStableType stable_type,
- const char * network_id,
- NMSettingIP6ConfigAddrGenMode addr_gen_mode,
- NMNDiscNodeType node_type,
- int max_addresses,
- int router_solicitations,
- int router_solicitation_interval,
- guint32 ra_timeout,
- GError ** error);
+NMNDisc *nm_lndp_ndisc_new(const NMNDiscConfig *config);
#endif /* __NETWORKMANAGER_LNDP_NDISC_H__ */
diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c
index d4f4a1850d..27b3b84586 100644
--- a/src/core/ndisc/nm-ndisc.c
+++ b/src/core/ndisc/nm-ndisc.c
@@ -7,16 +7,17 @@
#include "nm-ndisc.h"
-#include <stdlib.h>
#include <arpa/inet.h>
+#include <stdlib.h>
-#include "nm-setting-ip6-config.h"
-
-#include "nm-ndisc-private.h"
-#include "nm-utils.h"
+#include "libnm-platform/nm-platform-utils.h"
#include "libnm-platform/nm-platform.h"
#include "libnm-platform/nmp-netns.h"
#include "nm-l3-config-data.h"
+#include "nm-l3cfg.h"
+#include "nm-ndisc-private.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-utils.h"
#define _NMLOG_PREFIX_NAME "ndisc"
@@ -35,6 +36,8 @@ struct _NMNDiscPrivate {
/* this *must* be the first field. */
NMNDiscDataInternal rdata;
+ const NML3ConfigData *l3cd;
+
char *last_error;
GSource *ra_timeout_source;
@@ -51,37 +54,25 @@ struct _NMNDiscPrivate {
NMUtilsIPv6IfaceId iid;
- /* immutable values: */
- int ifindex;
- char * ifname;
- char * network_id;
- guint max_addresses;
- NMSettingIP6ConfigAddrGenMode addr_gen_mode;
- NMUtilsStableType stable_type;
- guint32 ra_timeout;
- gint32 router_solicitations;
- gint32 router_solicitation_interval;
- NMNDiscNodeType node_type;
-
- NMPlatform *platform;
- NMPNetns * netns;
+ /* immutable values from here on: */
+
+ union {
+ const NMNDiscConfig config;
+ NMNDiscConfig config_;
+ };
+
+ NMPNetns *netns;
};
typedef struct _NMNDiscPrivate NMNDiscPrivate;
-NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PLATFORM,
- PROP_IFINDEX,
- PROP_IFNAME,
- PROP_STABLE_TYPE,
- PROP_NETWORK_ID,
- PROP_ADDR_GEN_MODE,
- PROP_MAX_ADDRESSES,
- PROP_RA_TIMEOUT,
- PROP_ROUTER_SOLICITATIONS,
- PROP_ROUTER_SOLICITATION_INTERVAL,
- PROP_NODE_TYPE, );
+NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_CONFIG, );
-enum { CONFIG_RECEIVED, RA_TIMEOUT_SIGNAL, LAST_SIGNAL };
+enum {
+ CONFIG_RECEIVED,
+ RA_TIMEOUT_SIGNAL,
+ LAST_SIGNAL,
+};
static guint signals[LAST_SIGNAL] = {0};
@@ -110,15 +101,10 @@ NML3ConfigData *
nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
int ifindex,
const NMNDiscData * rdata,
- NMSettingIP6ConfigPrivacy ip6_privacy,
- guint32 route_table,
- guint32 route_metric,
- gboolean kernel_support_rta_pref,
- gboolean kernel_support_extended_ifa_flags)
+ NMSettingIP6ConfigPrivacy ip6_privacy)
{
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
guint32 ifa_flags;
- guint8 plen;
guint i;
const gint32 now_sec = nm_utils_get_monotonic_timestamp_sec();
@@ -126,20 +112,11 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
nm_l3_config_data_set_ip6_privacy(l3cd, ip6_privacy);
- /* Check, whether kernel is recent enough to help user space handling RA.
- * If it's not supported, we have no ipv6-privacy and must add autoconf
- * addresses as /128. The reason for the /128 is to prevent the kernel
- * from adding a prefix route for this address. */
- ifa_flags = 0;
- if (kernel_support_extended_ifa_flags) {
- ifa_flags |= IFA_F_NOPREFIXROUTE;
- if (NM_IN_SET(ip6_privacy,
- NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
- NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
- ifa_flags |= IFA_F_MANAGETEMPADDR;
- plen = 64;
- } else
- plen = 128;
+ ifa_flags = IFA_F_NOPREFIXROUTE;
+ if (NM_IN_SET(ip6_privacy,
+ NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
+ NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
+ ifa_flags |= IFA_F_MANAGETEMPADDR;
for (i = 0; i < rdata->addresses_n; i++) {
const NMNDiscAddress *ndisc_addr = &rdata->addresses[i];
@@ -148,7 +125,7 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
a = (NMPlatformIP6Address){
.ifindex = ifindex,
.address = ndisc_addr->address,
- .plen = plen,
+ .plen = 64,
.timestamp = now_sec,
.lifetime = _nm_ndisc_lifetime_from_expiry(((gint64) now_sec) * 1000,
ndisc_addr->expiry_msec,
@@ -174,8 +151,10 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
.plen = ndisc_route->plen,
.gateway = ndisc_route->gateway,
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
.rt_pref = ndisc_route->preference,
};
nm_assert((NMIcmpv6RouterPref) r.rt_pref == ndisc_route->preference);
@@ -184,12 +163,13 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
}
if (rdata->gateways_n > 0) {
- const NMIcmpv6RouterPref first_pref = rdata->gateways[0].preference;
- NMPlatformIP6Route r = {
+ NMPlatformIP6Route r = {
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
.ifindex = ifindex,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
for (i = 0; i < rdata->gateways_n; i++) {
@@ -197,13 +177,6 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
r.rt_pref = rdata->gateways[i].preference;
nm_assert((NMIcmpv6RouterPref) r.rt_pref == rdata->gateways[i].preference);
nm_l3_config_data_add_route_6(l3cd, &r);
-
- if (first_pref != rdata->gateways[i].preference && !kernel_support_rta_pref) {
- /* We are unable to configure a router preference. Hence, we skip all gateways
- * with a different preference from the first gateway. Note, that the gateways
- * are sorted in order of highest to lowest preference. */
- break;
- }
}
}
@@ -311,7 +284,7 @@ nm_ndisc_get_ifindex(NMNDisc *self)
{
g_return_val_if_fail(NM_IS_NDISC(self), 0);
- return NM_NDISC_GET_PRIVATE(self)->ifindex;
+ return nm_l3cfg_get_ifindex(NM_NDISC_GET_PRIVATE(self)->config.l3cfg);
}
const char *
@@ -319,7 +292,7 @@ nm_ndisc_get_ifname(NMNDisc *self)
{
g_return_val_if_fail(NM_IS_NDISC(self), NULL);
- return NM_NDISC_GET_PRIVATE(self)->ifname;
+ return NM_NDISC_GET_PRIVATE(self)->config.ifname;
}
NMNDiscNodeType
@@ -327,7 +300,7 @@ nm_ndisc_get_node_type(NMNDisc *self)
{
g_return_val_if_fail(NM_IS_NDISC(self), NM_NDISC_NODE_TYPE_INVALID);
- return NM_NDISC_GET_PRIVATE(self)->node_type;
+ return NM_NDISC_GET_PRIVATE(self)->config.node_type;
}
/*****************************************************************************/
@@ -387,15 +360,26 @@ _data_complete(NMNDiscDataInternal *data)
return &data->public;
}
-void
+static void
nm_ndisc_emit_config_change(NMNDisc *self, NMNDiscConfigMap changed)
{
+ NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(self);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMNDiscData * rdata;
+
_config_changed_log(self, changed);
- g_signal_emit(self,
- signals[CONFIG_RECEIVED],
- 0,
- _data_complete(&NM_NDISC_GET_PRIVATE(self)->rdata),
- (guint) changed);
+
+ rdata = _data_complete(&NM_NDISC_GET_PRIVATE(self)->rdata),
+
+ l3cd = nm_l3_config_data_seal(nm_ndisc_data_to_l3cd(nm_l3cfg_get_multi_idx(priv->config.l3cfg),
+ nm_l3cfg_get_ifindex(priv->config.l3cfg),
+ rdata,
+ priv->config.ip6_privacy));
+
+ if (!nm_l3_config_data_equal(priv->l3cd, l3cd))
+ NM_SWAP(&priv->l3cd, &l3cd);
+
+ g_signal_emit(self, signals[CONFIG_RECEIVED], 0, rdata, (guint) changed, priv->l3cd);
}
/*****************************************************************************/
@@ -475,11 +459,11 @@ complete_address(NMNDisc *ndisc, NMNDiscAddress *addr)
g_return_val_if_fail(NM_IS_NDISC(ndisc), FALSE);
priv = NM_NDISC_GET_PRIVATE(ndisc);
- if (priv->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) {
- if (!nm_utils_ipv6_addr_set_stable_privacy_may_fail(priv->stable_type,
+ if (priv->config.addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) {
+ if (!nm_utils_ipv6_addr_set_stable_privacy_may_fail(priv->config.stable_type,
&addr->address,
- priv->ifname,
- priv->network_id,
+ priv->config.ifname,
+ priv->config.network_id,
addr->dad_counter++,
&error)) {
_LOGW("complete-address: failed to generate an stable-privacy address: %s",
@@ -604,7 +588,7 @@ nm_ndisc_add_address(NMNDisc * ndisc,
* what the kernel does, because it considers *all* addresses (including
* static and other temporary addresses).
**/
- if (rdata->addresses->len >= priv->max_addresses)
+ if (rdata->addresses->len >= priv->config.max_addresses)
return FALSE;
if (new_item->expiry_msec <= now_msec)
@@ -893,7 +877,7 @@ solicit_timer_start(NMNDisc *ndisc)
g_random_int() % ((guint32) (NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY * 1000 / 4));
_LOGD("solicit: schedule sending first solicitation (of %d) in %.3f seconds",
- priv->router_solicitations,
+ priv->config.router_solicitations,
((double) delay_msec) / 1000);
priv->solicit_retransmit_time_msec = 0;
@@ -991,30 +975,85 @@ announce_router_solicited(NMNDisc *ndisc)
/*****************************************************************************/
void
-nm_ndisc_set_config(NMNDisc * ndisc,
- const GArray *addresses,
- const GArray *dns_servers,
- const GArray *dns_domains)
+nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd)
{
- gboolean changed = FALSE;
- guint i;
+ gboolean changed = FALSE;
+ const struct in6_addr *in6arr;
+ const char *const * strvarr;
+ NMDedupMultiIter iter;
+ const NMPObject * obj;
+ gint64 now_msec;
+ guint len;
+ guint i;
+
+ nm_assert(NM_IS_NDISC(ndisc));
+ nm_assert(nm_ndisc_get_node_type(ndisc) == NM_NDISC_NODE_TYPE_ROUTER);
+
+ now_msec = nm_utils_get_monotonic_timestamp_msec();
+
+ nm_l3_config_data_iter_obj_for_each (&iter, l3cd, &obj, NMP_OBJECT_TYPE_IP6_ADDRESS) {
+ const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS(obj);
+ guint32 preferred;
+ guint32 lifetime;
+ NMNDiscAddress a;
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&addr->address) || IN6_IS_ADDR_LINKLOCAL(&addr->address))
+ continue;
- for (i = 0; i < addresses->len; i++) {
- if (nm_ndisc_add_address(ndisc, &g_array_index(addresses, NMNDiscAddress, i), 0, FALSE))
+ if (addr->n_ifa_flags & IFA_F_TENTATIVE || addr->n_ifa_flags & IFA_F_DADFAILED)
+ continue;
+
+ if (addr->plen != 64)
+ continue;
+
+ lifetime = nmp_utils_lifetime_get(addr->timestamp,
+ addr->lifetime,
+ addr->preferred,
+ NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000,
+ &preferred);
+ if (!lifetime)
+ continue;
+
+ a = (NMNDiscAddress){
+ .address = addr->address,
+ .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, lifetime),
+ .expiry_preferred_msec =
+ _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, preferred),
+ };
+
+ if (nm_ndisc_add_address(ndisc, &a, now_msec, FALSE))
changed = TRUE;
}
- for (i = 0; i < dns_servers->len; i++) {
- if (nm_ndisc_add_dns_server(ndisc,
- &g_array_index(dns_servers, NMNDiscDNSServer, i),
- G_MININT64))
+ in6arr = NULL;
+ len = 0;
+ if (l3cd)
+ in6arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET6, &len);
+ for (i = 0; i < len; i++) {
+ NMNDiscDNSServer n;
+
+ n = (NMNDiscDNSServer){
+ .address = in6arr[i],
+ .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP,
+ NM_NDISC_ROUTER_LIFETIME),
+ };
+ if (nm_ndisc_add_dns_server(ndisc, &n, G_MININT64))
changed = TRUE;
}
- for (i = 0; i < dns_domains->len; i++) {
- if (nm_ndisc_add_dns_domain(ndisc,
- &g_array_index(dns_domains, NMNDiscDNSDomain, i),
- G_MININT64))
+ strvarr = NULL;
+ len = 0;
+ if (l3cd)
+ strvarr = nm_l3_config_data_get_searches(l3cd, AF_INET6, &len);
+ for (i = 0; i < len; i++) {
+ NMNDiscDNSDomain n;
+
+ n = (NMNDiscDNSDomain){
+ .domain = (char *) strvarr[i],
+ .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP,
+ NM_NDISC_ROUTER_LIFETIME),
+ };
+ if (nm_ndisc_add_dns_domain(ndisc, &n, G_MININT64))
changed = TRUE;
}
@@ -1055,7 +1094,7 @@ nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid)
if (priv->iid.id != iid.id) {
priv->iid = iid;
- if (priv->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY)
+ if (priv->config.addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY)
return FALSE;
if (rdata->addresses->len) {
@@ -1094,26 +1133,26 @@ nm_ndisc_start(NMNDisc *ndisc)
nm_assert(!priv->ra_timeout_source);
_LOGD("starting neighbor discovery for ifindex %d%s",
- priv->ifindex,
- priv->node_type == NM_NDISC_NODE_TYPE_HOST ? " (solicit)" : " (announce)");
+ nm_l3cfg_get_ifindex(priv->config.l3cfg),
+ priv->config.node_type == NM_NDISC_NODE_TYPE_HOST ? " (solicit)" : " (announce)");
if (!nm_ndisc_netns_push(ndisc, &netns))
return;
NM_NDISC_GET_CLASS(ndisc)->start(ndisc);
- if (priv->node_type == NM_NDISC_NODE_TYPE_HOST) {
+ if (priv->config.node_type == NM_NDISC_NODE_TYPE_HOST) {
G_STATIC_ASSERT_EXPR(NM_RA_TIMEOUT_DEFAULT == 0);
G_STATIC_ASSERT_EXPR(NM_RA_TIMEOUT_INFINITY == G_MAXINT32);
- nm_assert(priv->ra_timeout > 0u);
- nm_assert(priv->ra_timeout <= NM_RA_TIMEOUT_INFINITY);
+ nm_assert(priv->config.ra_timeout > 0u);
+ nm_assert(priv->config.ra_timeout <= NM_RA_TIMEOUT_INFINITY);
- if (priv->ra_timeout < NM_RA_TIMEOUT_INFINITY) {
+ if (priv->config.ra_timeout < NM_RA_TIMEOUT_INFINITY) {
guint timeout_msec;
- _LOGD("scheduling RA timeout in %u seconds", priv->ra_timeout);
- if (priv->ra_timeout < G_MAXUINT / 1000u)
- timeout_msec = priv->ra_timeout * 1000u;
+ _LOGD("scheduling RA timeout in %u seconds", priv->config.ra_timeout);
+ if (priv->config.ra_timeout < G_MAXUINT / 1000u)
+ timeout_msec = priv->config.ra_timeout * 1000u;
else
timeout_msec = G_MAXUINT;
priv->ra_timeout_source = nm_g_timeout_add_source(timeout_msec, ra_timeout_cb, ndisc);
@@ -1123,8 +1162,8 @@ nm_ndisc_start(NMNDisc *ndisc)
return;
}
- nm_assert(priv->ra_timeout == 0u);
- nm_assert(priv->node_type == NM_NDISC_NODE_TYPE_ROUTER);
+ nm_assert(priv->config.ra_timeout == 0u);
+ nm_assert(priv->config.node_type == NM_NDISC_NODE_TYPE_ROUTER);
announce_router_initial(ndisc);
}
@@ -1141,7 +1180,7 @@ nm_ndisc_stop(NMNDisc *ndisc)
nm_assert(NM_NDISC_GET_CLASS(ndisc)->stop);
- _LOGD("stopping neighbor discovery for ifindex %d", priv->ifindex);
+ _LOGD("stopping neighbor discovery for ifindex %d", nm_l3cfg_get_ifindex(priv->config.l3cfg));
if (!nm_ndisc_netns_push(ndisc, &netns))
return;
@@ -1368,7 +1407,7 @@ clean_addresses(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint
g_array_set_size(rdata->addresses, j);
}
- if (_array_set_size_max(rdata->gateways, priv->max_addresses))
+ if (_array_set_size_max(rdata->gateways, priv->config.max_addresses))
*changed |= NM_NDISC_CONFIG_ADDRESSES;
}
@@ -1624,85 +1663,87 @@ nm_ndisc_get_sysctl(NMPlatform *platform,
/*****************************************************************************/
static void
+_config_clear(NMNDiscConfig *config)
+{
+ g_clear_object(&config->l3cfg);
+ nm_clear_g_free((gpointer *) &config->ifname);
+ nm_clear_g_free((gpointer *) &config->network_id);
+}
+
+static void
+_config_init(NMNDiscConfig *config, const NMNDiscConfig *src)
+{
+ nm_assert(config);
+ g_return_if_fail(src);
+
+ /* we only allow to set @config if it was cleared (or is not yet initialized). */
+ nm_assert(!config->l3cfg);
+ nm_assert(!config->ifname);
+ nm_assert(!config->network_id);
+
+ g_return_if_fail(NM_IS_L3CFG(src->l3cfg));
+
+ *config = *src;
+
+ g_object_ref(config->l3cfg);
+ config->ifname = g_strdup(config->ifname);
+ config->network_id = g_strdup(config->network_id);
+
+ if (config->max_addresses <= 0)
+ config->max_addresses = _SIZE_MAX_ADDRESSES;
+ else if (config->max_addresses > 3u * _SIZE_MAX_ADDRESSES)
+ config->max_addresses = 3u * _SIZE_MAX_ADDRESSES;
+
+ /* This setter is only used in specific circumstances, and in this case,
+ * we expect that @src only contains valid settings. We thus assert that to
+ * be the case.*/
+ g_return_if_fail(config->ifname && config->ifname[0]);
+ g_return_if_fail(config->network_id);
+ g_return_if_fail(config->stable_type >= NM_UTILS_STABLE_TYPE_UUID
+ && config->stable_type <= NM_UTILS_STABLE_TYPE_RANDOM);
+ g_return_if_fail(config->addr_gen_mode >= NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64
+ && config->addr_gen_mode
+ <= NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY);
+ nm_assert(config->max_addresses >= 0 && config->max_addresses <= G_MAXINT32);
+ G_STATIC_ASSERT_EXPR(G_MAXINT32 == NM_RA_TIMEOUT_INFINITY);
+ g_return_if_fail(config->ra_timeout <= NM_RA_TIMEOUT_INFINITY);
+ g_return_if_fail(config->router_solicitations > 0
+ && config->router_solicitations <= G_MAXINT32);
+ g_return_if_fail(config->router_solicitation_interval > 0
+ && config->router_solicitation_interval <= G_MAXINT32);
+ g_return_if_fail(
+ NM_IN_SET(config->node_type, NM_NDISC_NODE_TYPE_HOST, NM_NDISC_NODE_TYPE_ROUTER));
+ g_return_if_fail(NM_IN_SET(config->ip6_privacy,
+ NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED,
+ NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR,
+ NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
+}
+
+/*****************************************************************************/
+
+static void
dns_domain_free(gpointer data)
{
g_free(((NMNDiscDNSDomain *) (data))->domain);
}
+/*****************************************************************************/
+
static void
set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
NMNDisc * self = NM_NDISC(object);
NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(self);
- int i;
switch (prop_id) {
- case PROP_PLATFORM:
+ case PROP_CONFIG:
/* construct-only */
- priv->platform = g_value_get_object(value) ?: NM_PLATFORM_GET;
- if (!priv->platform)
- g_return_if_reached();
-
- g_object_ref(priv->platform);
-
- priv->netns = nm_platform_netns_get(priv->platform);
- if (priv->netns)
- g_object_ref(priv->netns);
+ _config_init(&priv->config_, g_value_get_pointer(value));
+ priv->netns =
+ nm_g_object_ref(nm_platform_netns_get(nm_l3cfg_get_platform(priv->config.l3cfg)));
g_return_if_fail(!priv->netns || priv->netns == nmp_netns_get_current());
break;
- case PROP_IFINDEX:
- /* construct-only */
- priv->ifindex = g_value_get_int(value);
- g_return_if_fail(priv->ifindex > 0);
- break;
- case PROP_IFNAME:
- /* construct-only */
- priv->ifname = g_value_dup_string(value);
- g_return_if_fail(priv->ifname && priv->ifname[0]);
- break;
- case PROP_STABLE_TYPE:
- /* construct-only */
- priv->stable_type = g_value_get_int(value);
- break;
- case PROP_NETWORK_ID:
- /* construct-only */
- priv->network_id = g_value_dup_string(value);
- g_return_if_fail(priv->network_id);
- break;
- case PROP_ADDR_GEN_MODE:
- /* construct-only */
- priv->addr_gen_mode = g_value_get_int(value);
- break;
- case PROP_MAX_ADDRESSES:
- /* construct-only */
- i = g_value_get_int(value);
- nm_assert(i >= 0);
- priv->max_addresses = i;
-
- if (priv->max_addresses <= 0)
- priv->max_addresses = _SIZE_MAX_ADDRESSES;
- else if (priv->max_addresses > 3u * _SIZE_MAX_ADDRESSES)
- priv->max_addresses = 3u * _SIZE_MAX_ADDRESSES;
- break;
- case PROP_RA_TIMEOUT:
- /* construct-only */
- priv->ra_timeout = g_value_get_uint(value);
- nm_assert(priv->ra_timeout <= NM_RA_TIMEOUT_INFINITY);
- break;
- case PROP_ROUTER_SOLICITATIONS:
- /* construct-only */
- priv->router_solicitations = g_value_get_int(value);
- break;
- case PROP_ROUTER_SOLICITATION_INTERVAL:
- /* construct-only */
- priv->router_solicitation_interval = g_value_get_int(value);
- break;
- case PROP_NODE_TYPE:
- /* construct-only */
- priv->node_type = g_value_get_int(value);
- nm_assert(NM_IN_SET(priv->node_type, NM_NDISC_NODE_TYPE_HOST, NM_NDISC_NODE_TYPE_ROUTER));
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@@ -1752,9 +1793,6 @@ finalize(GObject *object)
NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc);
NMNDiscDataInternal *rdata = &priv->rdata;
- g_free(priv->ifname);
- g_free(priv->network_id);
-
g_array_unref(rdata->gateways);
g_array_unref(rdata->addresses);
g_array_unref(rdata->routes);
@@ -1762,7 +1800,10 @@ finalize(GObject *object)
g_array_unref(rdata->dns_domains);
g_clear_object(&priv->netns);
- g_clear_object(&priv->platform);
+
+ _config_clear(&priv->config_);
+
+ nm_clear_l3cd(&priv->l3cd);
G_OBJECT_CLASS(nm_ndisc_parent_class)->finalize(object);
}
@@ -1778,89 +1819,12 @@ nm_ndisc_class_init(NMNDiscClass *klass)
object_class->dispose = dispose;
object_class->finalize = finalize;
- obj_properties[PROP_PLATFORM] =
- g_param_spec_object(NM_NDISC_PLATFORM,
- "",
- "",
- NM_TYPE_PLATFORM,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IFINDEX] =
- g_param_spec_int(NM_NDISC_IFINDEX,
- "",
- "",
- 0,
- G_MAXINT,
- 0,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IFNAME] =
- g_param_spec_string(NM_NDISC_IFNAME,
- "",
- "",
- NULL,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_STABLE_TYPE] =
- g_param_spec_int(NM_NDISC_STABLE_TYPE,
- "",
- "",
- NM_UTILS_STABLE_TYPE_UUID,
- NM_UTILS_STABLE_TYPE_RANDOM,
- NM_UTILS_STABLE_TYPE_UUID,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_NETWORK_ID] =
- g_param_spec_string(NM_NDISC_NETWORK_ID,
- "",
- "",
- NULL,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDR_GEN_MODE] =
- g_param_spec_int(NM_NDISC_ADDR_GEN_MODE,
- "",
- "",
- NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
- NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY,
- NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_MAX_ADDRESSES] =
- g_param_spec_int(NM_NDISC_MAX_ADDRESSES,
- "",
- "",
- 0,
- G_MAXINT32,
- NM_NDISC_MAX_ADDRESSES_DEFAULT,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- G_STATIC_ASSERT_EXPR(G_MAXINT32 == NM_RA_TIMEOUT_INFINITY);
- obj_properties[PROP_RA_TIMEOUT] =
- g_param_spec_uint(NM_NDISC_RA_TIMEOUT,
- "",
- "",
- 0,
- G_MAXINT32,
- 0,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTER_SOLICITATIONS] =
- g_param_spec_int(NM_NDISC_ROUTER_SOLICITATIONS,
- "",
- "",
- 1,
- G_MAXINT32,
- NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTER_SOLICITATION_INTERVAL] =
- g_param_spec_int(NM_NDISC_ROUTER_SOLICITATION_INTERVAL,
- "",
- "",
- 1,
- G_MAXINT32,
- NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_NODE_TYPE] =
- g_param_spec_int(NM_NDISC_NODE_TYPE,
- "",
- "",
- NM_NDISC_NODE_TYPE_INVALID,
- NM_NDISC_NODE_TYPE_ROUTER,
- NM_NDISC_NODE_TYPE_INVALID,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_CONFIG] =
+ g_param_spec_pointer(NM_NDISC_CONFIG,
+ "",
+ "",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
signals[CONFIG_RECEIVED] = g_signal_new(NM_NDISC_CONFIG_RECEIVED,
@@ -1871,9 +1835,14 @@ nm_ndisc_class_init(NMNDiscClass *klass)
NULL,
NULL,
G_TYPE_NONE,
- 2,
- G_TYPE_POINTER,
- G_TYPE_UINT);
+ 3,
+ G_TYPE_POINTER
+ /* (const NMNDiscData *)rdata */,
+ G_TYPE_UINT
+ /* (guint) changed_i */,
+ G_TYPE_POINTER
+ /* (const NML3ConfigData *) l3cd */
+ );
signals[RA_TIMEOUT_SIGNAL] = g_signal_new(NM_NDISC_RA_TIMEOUT_SIGNAL,
G_OBJECT_CLASS_TYPE(klass),
G_SIGNAL_RUN_FIRST,
diff --git a/src/core/ndisc/nm-ndisc.h b/src/core/ndisc/nm-ndisc.h
index 5b82752815..90f574a90b 100644
--- a/src/core/ndisc/nm-ndisc.h
+++ b/src/core/ndisc/nm-ndisc.h
@@ -26,17 +26,7 @@
#define NM_IS_NDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_NDISC))
#define NM_NDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_NDISC, NMNDiscClass))
-#define NM_NDISC_PLATFORM "platform"
-#define NM_NDISC_IFINDEX "ifindex"
-#define NM_NDISC_IFNAME "ifname"
-#define NM_NDISC_NETWORK_ID "network-id"
-#define NM_NDISC_ADDR_GEN_MODE "addr-gen-mode"
-#define NM_NDISC_STABLE_TYPE "stable-type"
-#define NM_NDISC_NODE_TYPE "node-type"
-#define NM_NDISC_MAX_ADDRESSES "max-addresses"
-#define NM_NDISC_RA_TIMEOUT "ra-timeout"
-#define NM_NDISC_ROUTER_SOLICITATIONS "router-solicitations"
-#define NM_NDISC_ROUTER_SOLICITATION_INTERVAL "router-solicitation-interval"
+#define NM_NDISC_CONFIG "config"
#define NM_NDISC_CONFIG_RECEIVED "config-received"
#define NM_NDISC_RA_TIMEOUT_SIGNAL "ra-timeout-signal"
@@ -169,6 +159,20 @@ typedef enum {
#define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861, MaxRtrAdvInterval default */
#define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */
+typedef struct {
+ NML3Cfg * l3cfg;
+ const char * ifname;
+ const char * network_id;
+ int max_addresses;
+ int router_solicitations;
+ int router_solicitation_interval;
+ guint32 ra_timeout;
+ NMUtilsStableType stable_type;
+ NMSettingIP6ConfigAddrGenMode addr_gen_mode;
+ NMNDiscNodeType node_type;
+ NMSettingIP6ConfigPrivacy ip6_privacy;
+} NMNDiscConfig;
+
struct _NMNDiscPrivate;
struct _NMNDiscDataInternal;
@@ -217,8 +221,6 @@ typedef struct {
GType nm_ndisc_get_type(void);
-void nm_ndisc_emit_config_change(NMNDisc *self, NMNDiscConfigMap changed);
-
int nm_ndisc_get_ifindex(NMNDisc *self);
const char * nm_ndisc_get_ifname(NMNDisc *self);
NMNDiscNodeType nm_ndisc_get_node_type(NMNDisc *self);
@@ -228,10 +230,7 @@ void nm_ndisc_start(NMNDisc *ndisc);
void nm_ndisc_stop(NMNDisc *ndisc);
NMNDiscConfigMap
nm_ndisc_dad_failed(NMNDisc *ndisc, const struct in6_addr *address, gboolean emit_changed_signal);
-void nm_ndisc_set_config(NMNDisc * ndisc,
- const GArray *addresses,
- const GArray *dns_servers,
- const GArray *dns_domains);
+void nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd);
NMPlatform *nm_ndisc_get_platform(NMNDisc *self);
NMPNetns * nm_ndisc_netns_get(NMNDisc *self);
@@ -280,10 +279,6 @@ struct _NML3ConfigData;
struct _NML3ConfigData *nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
int ifindex,
const NMNDiscData * rdata,
- NMSettingIP6ConfigPrivacy ip6_privacy,
- guint32 route_table,
- guint32 route_metric,
- gboolean kernel_support_rta_pref,
- gboolean kernel_support_extended_ifa_flags);
+ NMSettingIP6ConfigPrivacy ip6_privacy);
#endif /* __NETWORKMANAGER_NDISC_H__ */
diff --git a/src/core/ndisc/tests/test-ndisc-fake.c b/src/core/ndisc/tests/test-ndisc-fake.c
index f201bc5641..2507a484e8 100644
--- a/src/core/ndisc/tests/test-ndisc-fake.c
+++ b/src/core/ndisc/tests/test-ndisc-fake.c
@@ -11,23 +11,28 @@
#include "ndisc/nm-fake-ndisc.h"
#include "platform/nm-fake-platform.h"
+#include "nm-netns.h"
-#include "nm-test-utils-core.h"
+#include "platform/tests/test-common.h"
/*****************************************************************************/
static NMFakeNDisc *
ndisc_new(void)
{
- NMNDisc * ndisc;
- const int ifindex = 1;
- const char * ifname = nm_platform_link_get_name(NM_PLATFORM_GET, ifindex);
- NMUtilsIPv6IfaceId iid = {};
+ gs_unref_object NML3Cfg *l3cfg = NULL;
+ NMNDisc * ndisc;
+ const int ifindex = 1;
+ NMUtilsIPv6IfaceId iid;
- ndisc = nm_fake_ndisc_new(ifindex, ifname);
+ l3cfg = nm_netns_access_l3cfg(NM_NETNS_GET, ifindex);
+
+ ndisc = nm_fake_ndisc_new(l3cfg);
+ g_assert(ndisc);
+
+ memset(&iid, 0, sizeof(iid));
iid.id_u8[7] = 1;
nm_ndisc_set_iid(ndisc, iid);
- g_assert(ndisc);
return NM_FAKE_NDISC(ndisc);
}
@@ -140,9 +145,15 @@ typedef struct {
/*****************************************************************************/
static void
-test_simple_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data)
+test_simple_changed(NMNDisc * ndisc,
+ const NMNDiscData * rdata,
+ guint changed_i,
+ const NML3ConfigData *l3cd,
+ TestData * data)
{
- NMNDiscConfigMap changed = changed_int;
+ NMNDiscConfigMap changed = changed_i;
+
+ _LOGT("test_simple: callback (counter=%u)", data->counter);
switch (data->counter++) {
case 0:
@@ -206,9 +217,11 @@ test_simple(void)
g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_simple_changed), &data);
+ _LOGT("test_simple: start");
nm_ndisc_start(NM_NDISC(ndisc));
nmtst_main_loop_run_assert(data.loop, 15000);
g_assert_cmpint(data.counter, ==, 2);
+ _LOGT("test_simple: done");
}
/*****************************************************************************/
@@ -221,9 +234,13 @@ test_everything_rs_sent(NMNDisc *ndisc, TestData *data)
}
static void
-test_everything_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data)
+test_everything_changed(NMNDisc * ndisc,
+ const NMNDiscData * rdata,
+ guint changed_i,
+ const NML3ConfigData *l3cd,
+ TestData * data)
{
- NMNDiscConfigMap changed = changed_int;
+ NMNDiscConfigMap changed = changed_i;
if (data->counter == 0) {
g_assert_cmpint(data->rs_counter, ==, 1);
@@ -342,12 +359,13 @@ test_everything(void)
}
static void
-test_preference_order_cb(NMNDisc * ndisc,
- const NMNDiscData *rdata,
- guint changed_int,
- TestData * data)
+test_preference_order_cb(NMNDisc * ndisc,
+ const NMNDiscData * rdata,
+ guint changed_i,
+ const NML3ConfigData *l3cd,
+ TestData * data)
{
- NMNDiscConfigMap changed = changed_int;
+ NMNDiscConfigMap changed = changed_i;
if (data->counter == 1) {
g_assert_cmpint(changed,
@@ -434,12 +452,13 @@ test_preference_order(void)
}
static void
-test_preference_changed_cb(NMNDisc * ndisc,
- const NMNDiscData *rdata,
- guint changed_int,
- TestData * data)
+test_preference_changed_cb(NMNDisc * ndisc,
+ const NMNDiscData * rdata,
+ guint changed_i,
+ const NML3ConfigData *l3cd,
+ TestData * data)
{
- NMNDiscConfigMap changed = changed_int;
+ NMNDiscConfigMap changed = changed_i;
if (data->counter == 1) {
g_assert_cmpint(changed,
@@ -576,10 +595,11 @@ test_preference_changed(void)
/*****************************************************************************/
static void
-_test_dns_solicit_loop_changed(NMNDisc * ndisc,
- const NMNDiscData *rdata,
- guint changed_int,
- TestData * data)
+_test_dns_solicit_loop_changed(NMNDisc * ndisc,
+ const NMNDiscData * rdata,
+ guint changed_i,
+ const NML3ConfigData *l3cd,
+ TestData * data)
{
data->counter++;
}
diff --git a/src/core/ndisc/tests/test-ndisc-linux.c b/src/core/ndisc/tests/test-ndisc-linux.c
index 57021606d3..57ca7b2b58 100644
--- a/src/core/ndisc/tests/test-ndisc-linux.c
+++ b/src/core/ndisc/tests/test-ndisc-linux.c
@@ -11,6 +11,8 @@
#include "ndisc/nm-lndp-ndisc.h"
#include "libnm-platform/nm-linux-platform.h"
+#include "nm-netns.h"
+#include "nm-l3cfg.h"
#include "nm-test-utils-core.h"
@@ -19,16 +21,18 @@ NMTST_DEFINE();
int
main(int argc, char **argv)
{
- GMainLoop * loop;
- NMNDisc * ndisc;
- int ifindex = 1;
- const char * ifname;
- NMUtilsIPv6IfaceId iid = {};
- GError * error = NULL;
- int max_addresses;
- int router_solicitations;
- int router_solicitation_interval;
- guint32 ra_timeout;
+ gs_unref_object NML3Cfg *l3cfg = NULL;
+ NMNDiscConfig config;
+ GMainLoop * loop;
+ NMNDisc * ndisc;
+ int ifindex = 1;
+ const char * ifname;
+ NMUtilsIPv6IfaceId iid = {};
+ GError * error = NULL;
+ int max_addresses;
+ int router_solicitations;
+ int router_solicitation_interval;
+ guint32 ra_timeout;
nmtst_init_with_logging(&argc, &argv, NULL, "DEFAULT");
@@ -56,18 +60,23 @@ main(int argc, char **argv)
&router_solicitation_interval,
&ra_timeout);
- ndisc = nm_lndp_ndisc_new(NM_PLATFORM_GET,
- ifindex,
- ifname,
- NM_UTILS_STABLE_TYPE_UUID,
- "8ce666e8-d34d-4fb1-b858-f15a7al28086",
- NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
- NM_NDISC_NODE_TYPE_HOST,
- max_addresses,
- router_solicitations,
- router_solicitation_interval,
- ra_timeout,
- &error);
+ l3cfg = nm_netns_access_l3cfg(NM_NETNS_GET, ifindex);
+
+ config = (NMNDiscConfig){
+ .l3cfg = l3cfg,
+ .ifname = nm_l3cfg_get_ifname(l3cfg, TRUE),
+ .stable_type = NM_UTILS_STABLE_TYPE_UUID,
+ .network_id = "8ce666e8-d34d-4fb1-b858-f15a7al28086",
+ .addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
+ .node_type = NM_NDISC_NODE_TYPE_HOST,
+ .max_addresses = max_addresses,
+ .router_solicitations = router_solicitations,
+ .router_solicitation_interval = router_solicitation_interval,
+ .ra_timeout = ra_timeout,
+ .ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
+ };
+
+ ndisc = nm_lndp_ndisc_new(&config);
if (!ndisc) {
g_print("Failed to create NMNDisc instance: %s\n", error->message);
g_error_free(error);
diff --git a/src/core/nm-act-request.c b/src/core/nm-act-request.c
index d0a2e0c783..58dd4a87f8 100644
--- a/src/core/nm-act-request.c
+++ b/src/core/nm-act-request.c
@@ -24,8 +24,7 @@
#include "settings/nm-settings-connection.h"
typedef struct {
- CList call_ids_lst_head;
- NMFirewallConfig *firewall_config;
+ CList call_ids_lst_head;
} NMActRequestPrivate;
struct _NMActRequest {
@@ -250,36 +249,6 @@ nm_act_request_clear_secrets(NMActRequest *self)
/*****************************************************************************/
-NMFirewallConfig *
-nm_act_request_get_shared(NMActRequest *req)
-{
- g_return_val_if_fail(NM_IS_ACT_REQUEST(req), FALSE);
-
- return NM_ACT_REQUEST_GET_PRIVATE(req)->firewall_config;
-}
-
-void
-nm_act_request_set_shared(NMActRequest *req, NMFirewallConfig *rules)
-{
- NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(req);
-
- g_return_if_fail(NM_IS_ACT_REQUEST(req));
-
- if (priv->firewall_config == rules)
- return;
-
- if (priv->firewall_config) {
- nm_firewall_config_apply(priv->firewall_config, FALSE);
- priv->firewall_config = NULL;
- }
- if (rules) {
- priv->firewall_config = rules;
- nm_firewall_config_apply(priv->firewall_config, TRUE);
- }
-}
-
-/*****************************************************************************/
-
static void
device_notify(GObject *object, GParamSpec *pspec, gpointer self)
{
@@ -508,11 +477,6 @@ dispose(GObject *object)
c_list_for_each_entry_safe (call_id, call_id_safe, &priv->call_ids_lst_head, call_ids_lst)
_do_cancel_secrets(self, call_id, TRUE);
- if (priv->firewall_config) {
- nm_firewall_config_apply(priv->firewall_config, FALSE);
- nm_clear_pointer(&priv->firewall_config, nm_firewall_config_free);
- }
-
G_OBJECT_CLASS(nm_act_request_parent_class)->dispose(object);
}
diff --git a/src/core/nm-act-request.h b/src/core/nm-act-request.h
index 9c702d31eb..698a9985a4 100644
--- a/src/core/nm-act-request.h
+++ b/src/core/nm-act-request.h
@@ -38,14 +38,6 @@ NMConnection *nm_act_request_get_applied_connection(NMActRequest *req);
/*****************************************************************************/
-struct _NMFirewallConfig;
-
-struct _NMFirewallConfig *nm_act_request_get_shared(NMActRequest *req);
-
-void nm_act_request_set_shared(NMActRequest *req, struct _NMFirewallConfig *rules);
-
-/*****************************************************************************/
-
/* Secrets handling */
typedef void (*NMActRequestSecretsFunc)(NMActRequest * req,
diff --git a/src/core/nm-active-connection.h b/src/core/nm-active-connection.h
index 15c68e6e7e..1c2c8116ba 100644
--- a/src/core/nm-active-connection.h
+++ b/src/core/nm-active-connection.h
@@ -138,6 +138,9 @@ void nm_active_connection_set_state_fail(NMActiveConnection * active,
NMActiveConnectionStateReason reason,
const char * error_desc);
+#define NM_ACTIVATION_STATE_FLAG_IP_READY_X(IS_IPv4) \
+ ((IS_IPv4) ? NM_ACTIVATION_STATE_FLAG_IP4_READY : NM_ACTIVATION_STATE_FLAG_IP6_READY)
+
NMActivationStateFlags nm_active_connection_get_state_flags(NMActiveConnection *self);
void nm_active_connection_set_state_flags_full(NMActiveConnection * self,
diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c
index 1cb8a43c32..0c4f8099de 100644
--- a/src/core/nm-config-data.c
+++ b/src/core/nm-config-data.c
@@ -929,59 +929,57 @@ nm_global_dns_config_is_empty(const NMGlobalDnsConfig *dns_config)
return !dns_config->searches && !dns_config->options && !dns_config->domain_list;
}
-void
-nm_global_dns_config_update_checksum(const NMGlobalDnsConfig *dns_config, GChecksum *sum)
+int
+nm_global_dns_config_cmp(const NMGlobalDnsConfig *a,
+ const NMGlobalDnsConfig *b,
+ gboolean check_internal)
{
- NMGlobalDnsDomain *domain;
- guint i, j;
- guint8 v8;
+ guint i;
- g_return_if_fail(dns_config);
- g_return_if_fail(sum);
+ NM_CMP_SELF(a, b);
- v8 = NM_HASH_COMBINE_BOOLS(guint8,
- !dns_config->searches,
- !dns_config->options,
- !dns_config->domain_list);
- g_checksum_update(sum, (guchar *) &v8, 1);
+ NM_CMP_RETURN(
+ nm_strv_cmp_n(a->searches ?: NM_STRV_EMPTY(), -1, b->searches ?: NM_STRV_EMPTY(), -1));
- if (dns_config->searches) {
- for (i = 0; dns_config->searches[i]; i++)
- g_checksum_update(sum,
- (guchar *) dns_config->searches[i],
- strlen(dns_config->searches[i]) + 1);
- }
- if (dns_config->options) {
- for (i = 0; dns_config->options[i]; i++)
- g_checksum_update(sum,
- (guchar *) dns_config->options[i],
- strlen(dns_config->options[i]) + 1);
- }
+ NM_CMP_RETURN(
+ nm_strv_cmp_n(a->options ?: NM_STRV_EMPTY(), -1, b->options ?: NM_STRV_EMPTY(), -1));
- if (dns_config->domain_list) {
- for (i = 0; dns_config->domain_list[i]; i++) {
- domain = g_hash_table_lookup(dns_config->domains, dns_config->domain_list[i]);
- nm_assert(domain);
+ NM_CMP_RETURN(nm_strv_cmp_n(a->domain_list ?: NM_STRV_EMPTY_CC(),
+ -1,
+ b->domain_list ?: NM_STRV_EMPTY_CC(),
+ -1));
- v8 = NM_HASH_COMBINE_BOOLS(guint8, !domain->servers, !domain->options);
- g_checksum_update(sum, (guchar *) &v8, 1);
+ if (a->domain_list) {
+ for (i = 0; a->domain_list[i]; i++) {
+ const NMGlobalDnsDomain *domain_a;
+ const NMGlobalDnsDomain *domain_b;
- g_checksum_update(sum, (guchar *) domain->name, strlen(domain->name) + 1);
+ nm_assert(nm_streq(a->domain_list[i], b->domain_list[i]));
- if (domain->servers) {
- for (j = 0; domain->servers[j]; j++)
- g_checksum_update(sum,
- (guchar *) domain->servers[j],
- strlen(domain->servers[j]) + 1);
- }
- if (domain->options) {
- for (j = 0; domain->options[j]; j++)
- g_checksum_update(sum,
- (guchar *) domain->options[j],
- strlen(domain->options[j]) + 1);
- }
+ domain_a = g_hash_table_lookup(a->domains, a->domain_list[i]);
+ nm_assert(domain_a);
+
+ domain_b = g_hash_table_lookup(b->domains, b->domain_list[i]);
+ nm_assert(domain_b);
+
+ NM_CMP_FIELD_STR0(domain_a, domain_b, name);
+
+ NM_CMP_RETURN(nm_strv_cmp_n(domain_a->servers ?: NM_STRV_EMPTY(),
+ -1,
+ domain_b->servers ?: NM_STRV_EMPTY(),
+ -1));
+
+ NM_CMP_RETURN(nm_strv_cmp_n(domain_a->options ?: NM_STRV_EMPTY(),
+ -1,
+ domain_b->options ?: NM_STRV_EMPTY(),
+ -1));
}
}
+
+ if (check_internal)
+ NM_CMP_FIELD(a, b, internal);
+
+ return 0;
}
static void
diff --git a/src/core/nm-config-data.h b/src/core/nm-config-data.h
index fa58d869c7..9ac2a65e23 100644
--- a/src/core/nm-config-data.h
+++ b/src/core/nm-config-data.h
@@ -264,8 +264,10 @@ const char *const *nm_global_dns_domain_get_servers(const NMGlobalDnsDomain *dom
const char *const *nm_global_dns_domain_get_options(const NMGlobalDnsDomain *domain);
gboolean nm_global_dns_config_is_internal(const NMGlobalDnsConfig *dns_config);
gboolean nm_global_dns_config_is_empty(const NMGlobalDnsConfig *dns_config);
-void nm_global_dns_config_update_checksum(const NMGlobalDnsConfig *dns_config, GChecksum *sum);
-void nm_global_dns_config_free(NMGlobalDnsConfig *dns_config);
+int nm_global_dns_config_cmp(const NMGlobalDnsConfig *a,
+ const NMGlobalDnsConfig *b,
+ gboolean check_internal);
+void nm_global_dns_config_free(NMGlobalDnsConfig *dns_config);
NMGlobalDnsConfig *nm_global_dns_config_from_dbus(const GValue *value, GError **error);
void nm_global_dns_config_to_dbus(const NMGlobalDnsConfig *dns_config, GValue *value);
diff --git a/src/core/nm-connectivity.c b/src/core/nm-connectivity.c
index 13fb026514..230c4afe53 100644
--- a/src/core/nm-connectivity.c
+++ b/src/core/nm-connectivity.c
@@ -15,6 +15,7 @@
#include <linux/rtnetlink.h>
#include "c-list/src/c-list.h"
+#include "libnm-platform/nmp-object.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-config.h"
#include "NetworkManagerUtils.h"
diff --git a/src/core/nm-dhcp-config.c b/src/core/nm-dhcp-config.c
index 8a02911942..8a89173c0f 100644
--- a/src/core/nm-dhcp-config.c
+++ b/src/core/nm-dhcp-config.c
@@ -8,9 +8,11 @@
#include "nm-dhcp-config.h"
#include "nm-dbus-interface.h"
+#include "NetworkManagerUtils.h"
#include "nm-utils.h"
#include "nm-dbus-object.h"
#include "nm-core-utils.h"
+#include "nm-l3-config-data.h"
/*****************************************************************************/
@@ -46,10 +48,11 @@ static GType nm_dhcp6_config_get_type(void);
/*****************************************************************************/
-NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpConfig, PROP_OPTIONS, );
+NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpConfig, PROP_L3CD, PROP_OPTIONS, );
typedef struct {
- GVariant *options;
+ const NML3ConfigData *l3cd;
+ GVariant * options;
} NMDhcpConfigPrivate;
struct _NMDhcpConfig {
@@ -76,18 +79,49 @@ nm_dhcp_config_get_addr_family(NMDhcpConfig *self)
/*****************************************************************************/
+static GVariant *
+_l3cd_to_options(const NML3ConfigData *l3cd, int addr_family)
+{
+ GVariant *options;
+
+ options = NULL;
+ if (l3cd) {
+ NMDhcpLease *lease;
+
+ lease = nm_l3_config_data_get_dhcp_lease(l3cd, addr_family);
+ if (lease)
+ options = nm_strdict_to_variant_asv(nm_dhcp_lease_get_options(lease));
+ }
+ if (!options)
+ options = nm_g_variant_singleton_aLsvI();
+ return g_variant_ref_sink(options);
+}
+
void
-nm_dhcp_config_set_options(NMDhcpConfig *self, GHashTable *options)
+nm_dhcp_config_set_lease(NMDhcpConfig *self, const NML3ConfigData *l3cd)
{
- NMDhcpConfigPrivate *priv;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
+ gs_unref_variant GVariant *options2 = NULL;
+ NMDhcpConfigPrivate * priv;
g_return_if_fail(NM_IS_DHCP_CONFIG(self));
- g_return_if_fail(options);
priv = NM_DHCP_CONFIG_GET_PRIVATE(self);
- nm_g_variant_unref(priv->options);
- priv->options = g_variant_ref_sink(nm_strdict_to_variant_asv(options));
+ if (priv->l3cd == l3cd)
+ return;
+
+ l3cd_old = g_steal_pointer(&priv->l3cd);
+ if (l3cd)
+ priv->l3cd = nm_l3_config_data_ref_and_seal(l3cd);
+
+ options2 = _l3cd_to_options(priv->l3cd, nm_dhcp_config_get_addr_family(self));
+
+ if (g_variant_equal(priv->options, options2))
+ return;
+
+ NM_SWAP(&priv->options, &options2);
+
_notify(self, PROP_OPTIONS);
}
@@ -95,19 +129,22 @@ const char *
nm_dhcp_config_get_option(NMDhcpConfig *self, const char *key)
{
NMDhcpConfigPrivate *priv;
- const char * value;
+ NMDhcpLease * lease;
g_return_val_if_fail(NM_IS_DHCP_CONFIG(self), NULL);
g_return_val_if_fail(key, NULL);
priv = NM_DHCP_CONFIG_GET_PRIVATE(self);
- if (priv->options && g_variant_lookup(priv->options, key, "&s", &value))
- return value;
- else
+ if (!priv->l3cd)
return NULL;
+
+ lease = nm_l3_config_data_get_dhcp_lease(priv->l3cd, nm_dhcp_config_get_addr_family(self));
+ return nm_dhcp_lease_lookup_option(lease, key);
}
+/*****************************************************************************/
+
GVariant *
nm_dhcp_config_get_options(NMDhcpConfig *self)
{
@@ -125,7 +162,25 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
switch (prop_id) {
case PROP_OPTIONS:
- g_value_set_variant(value, priv->options ?: nm_g_variant_singleton_aLsvI());
+ g_value_set_variant(value, priv->options);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ NMDhcpConfig * self = NM_DHCP_CONFIG(object);
+ NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE(self);
+
+ switch (prop_id) {
+ case PROP_L3CD:
+ /* construct-only */
+ priv->l3cd = nm_l3_config_data_ref_and_seal(g_value_get_pointer(value));
+ priv->options = _l3cd_to_options(priv->l3cd, nm_dhcp_config_get_addr_family(self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -140,11 +195,12 @@ nm_dhcp_config_init(NMDhcpConfig *self)
{}
NMDhcpConfig *
-nm_dhcp_config_new(int addr_family)
+nm_dhcp_config_new(int addr_family, const NML3ConfigData *l3cd)
{
- nm_assert_addr_family(addr_family);
-
- return g_object_new(addr_family != AF_INET ? NM_TYPE_DHCP6_CONFIG : NM_TYPE_DHCP4_CONFIG, NULL);
+ return g_object_new(NM_IS_IPv4(addr_family) ? NM_TYPE_DHCP4_CONFIG : NM_TYPE_DHCP6_CONFIG,
+ NM_DHCP_CONFIG_L3CD,
+ l3cd,
+ NULL);
}
static void
@@ -152,7 +208,9 @@ finalize(GObject *object)
{
NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE(object);
- nm_g_variant_unref(priv->options);
+ g_variant_unref(priv->options);
+
+ nm_l3_config_data_unref(priv->l3cd);
G_OBJECT_CLASS(nm_dhcp_config_parent_class)->finalize(object);
}
@@ -163,8 +221,15 @@ nm_dhcp_config_class_init(NMDhcpConfigClass *config_class)
GObjectClass *object_class = G_OBJECT_CLASS(config_class);
object_class->get_property = get_property;
+ object_class->set_property = set_property;
object_class->finalize = finalize;
+ obj_properties[PROP_L3CD] =
+ g_param_spec_pointer(NM_DHCP_CONFIG_L3CD,
+ "",
+ "",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
obj_properties[PROP_OPTIONS] = g_param_spec_variant(NM_DHCP_CONFIG_OPTIONS,
"",
"",
diff --git a/src/core/nm-dhcp-config.h b/src/core/nm-dhcp-config.h
index 9e68f2fb3a..cae0e11aa2 100644
--- a/src/core/nm-dhcp-config.h
+++ b/src/core/nm-dhcp-config.h
@@ -18,16 +18,17 @@
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_CONFIG, NMDhcpConfigClass))
#define NM_DHCP_CONFIG_OPTIONS "options"
+#define NM_DHCP_CONFIG_L3CD "l3cd"
typedef struct _NMDhcpConfigClass NMDhcpConfigClass;
GType nm_dhcp_config_get_type(void);
-NMDhcpConfig *nm_dhcp_config_new(int addr_family);
+NMDhcpConfig *nm_dhcp_config_new(int addr_family, const NML3ConfigData *l3cd);
int nm_dhcp_config_get_addr_family(NMDhcpConfig *self);
-void nm_dhcp_config_set_options(NMDhcpConfig *self, GHashTable *options);
+void nm_dhcp_config_set_lease(NMDhcpConfig *self, const NML3ConfigData *l3cd);
const char *nm_dhcp_config_get_option(NMDhcpConfig *self, const char *option);
diff --git a/src/core/nm-dispatcher.c b/src/core/nm-dispatcher.c
index b77197863b..d68dab5b22 100644
--- a/src/core/nm-dispatcher.c
+++ b/src/core/nm-dispatcher.c
@@ -15,9 +15,7 @@
#include "nm-act-request.h"
#include "devices/nm-device.h"
#include "nm-dhcp-config.h"
-#include "nm-proxy-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "nm-l3-config-data.h"
#include "nm-manager.h"
#include "settings/nm-settings-connection.h"
#include "libnm-platform/nm-platform.h"
@@ -148,50 +146,47 @@ _init_dispatcher(void)
/*****************************************************************************/
static void
-dump_proxy_to_props(NMProxyConfig *proxy, GVariantBuilder *builder)
+dump_proxy_to_props(const NML3ConfigData *l3cd, GVariantBuilder *builder)
{
- const char *pac_url = NULL, *pac_script = NULL;
+ const char *s;
- if (nm_proxy_config_get_method(proxy) == NM_PROXY_CONFIG_METHOD_NONE)
+ if (nm_l3_config_data_get_proxy_method(l3cd) != NM_PROXY_CONFIG_METHOD_AUTO)
return;
- pac_url = nm_proxy_config_get_pac_url(proxy);
- if (pac_url) {
- g_variant_builder_add(builder, "{sv}", "pac-url", g_variant_new_string(pac_url));
- }
+ s = nm_l3_config_data_get_proxy_pac_url(l3cd);
+ if (s)
+ g_variant_builder_add(builder, "{sv}", "pac-url", g_variant_new_string(s));
- pac_script = nm_proxy_config_get_pac_script(proxy);
- if (pac_script) {
- g_variant_builder_add(builder, "{sv}", "pac-script", g_variant_new_string(pac_script));
- }
+ s = nm_l3_config_data_get_proxy_pac_script(l3cd);
+ if (s)
+ g_variant_builder_add(builder, "{sv}", "pac-script", g_variant_new_string(s));
}
static void
-dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder)
+dump_ip_to_props(const NML3ConfigData *l3cd, int addr_family, GVariantBuilder *builder)
{
- const int addr_family = nm_ip_config_get_addr_family(ip);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- const NMPObject *obj;
- GVariantBuilder int_builder;
- NMDedupMultiIter ipconf_iter;
- GVariant * var1;
- GVariant * var2;
- guint n;
- guint i;
- const NMPObject *default_route;
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ const NMPObject * obj;
+ GVariantBuilder int_builder;
+ NMDedupMultiIter ipconf_iter;
+ GVariant * var1;
+ GVariant * var2;
+ guint n;
+ guint i;
+ const NMPObject * default_route;
+ const char *const *strarr;
+ const in_addr_t * ip4arr;
+ gconstpointer iparr;
if (IS_IPv4)
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aau"));
else
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("a(ayuay)"));
- default_route = nm_ip_config_best_default_route_get(ip);
- if (IS_IPv4)
- nm_ip_config_iter_ip4_address_init(&ipconf_iter, NM_IP4_CONFIG(ip));
- else
- nm_ip_config_iter_ip6_address_init(&ipconf_iter, NM_IP6_CONFIG(ip));
- while (nm_platform_dedup_multi_iter_next_obj(&ipconf_iter,
- &obj,
- NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4))) {
+ default_route = nm_l3_config_data_get_best_default_route(l3cd, addr_family);
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &obj,
+ NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) {
const NMPlatformIPXAddress *addr = NMP_OBJECT_CAST_IPX_ADDRESS(obj);
if (IS_IPv4) {
@@ -225,30 +220,28 @@ dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder)
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au"));
else
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aay"));
- n = nm_ip_config_get_num_nameservers(ip);
+ iparr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &n);
for (i = 0; i < n; i++) {
- if (IS_IPv4) {
- g_variant_builder_add(&int_builder,
- "u",
- nm_ip4_config_get_nameserver(NM_IP4_CONFIG(ip), i));
- } else {
- var1 = nm_g_variant_new_ay_in6addr(nm_ip6_config_get_nameserver(NM_IP6_CONFIG(ip), i));
+ if (IS_IPv4)
+ g_variant_builder_add(&int_builder, "u", ((const in_addr_t *) iparr)[i]);
+ else {
+ var1 = nm_g_variant_new_ay_in6addr(&(((const struct in6_addr *) iparr)[i]));
g_variant_builder_add(&int_builder, "@ay", var1);
}
}
g_variant_builder_add(builder, "{sv}", "nameservers", g_variant_builder_end(&int_builder));
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("as"));
- n = nm_ip_config_get_num_domains(ip);
+ strarr = nm_l3_config_data_get_domains(l3cd, addr_family, &n);
for (i = 0; i < n; i++)
- g_variant_builder_add(&int_builder, "s", nm_ip_config_get_domain(ip, i));
+ g_variant_builder_add(&int_builder, "s", strarr[i]);
g_variant_builder_add(builder, "{sv}", "domains", g_variant_builder_end(&int_builder));
if (IS_IPv4) {
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au"));
- n = nm_ip4_config_get_num_wins(NM_IP4_CONFIG(ip));
+ ip4arr = nm_l3_config_data_get_wins(l3cd, &n);
for (i = 0; i < n; i++)
- g_variant_builder_add(&int_builder, "u", nm_ip4_config_get_wins(NM_IP4_CONFIG(ip), i));
+ g_variant_builder_add(&int_builder, "u", ip4arr[i]);
g_variant_builder_add(builder, "{sv}", "wins-servers", g_variant_builder_end(&int_builder));
}
@@ -256,13 +249,10 @@ dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder)
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aau"));
else
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("a(ayuayu)"));
- if (IS_IPv4)
- nm_ip_config_iter_ip4_route_init(&ipconf_iter, NM_IP4_CONFIG(ip));
- else
- nm_ip_config_iter_ip6_route_init(&ipconf_iter, NM_IP6_CONFIG(ip));
- while (nm_platform_dedup_multi_iter_next_obj(&ipconf_iter,
- &obj,
- NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))) {
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &obj,
+ NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) {
const NMPlatformIPXRoute *route = NMP_OBJECT_CAST_IPX_ROUTE(obj);
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
@@ -299,10 +289,8 @@ fill_device_props(NMDevice * device,
GVariant ** dhcp4_props,
GVariant ** dhcp6_props)
{
- NMProxyConfig *proxy_config;
- NMIP4Config * ip4_config;
- NMIP6Config * ip6_config;
- NMDhcpConfig * dhcp_config;
+ const NML3ConfigData *l3cd;
+ NMDhcpConfig * dhcp_config;
/* If the action is for a VPN, send the VPN's IP interface instead of the device's */
g_variant_builder_add(dev_builder,
@@ -329,17 +317,12 @@ fill_device_props(NMDevice * device,
g_variant_new_object_path(nm_dbus_object_get_path(NM_DBUS_OBJECT(device))));
}
- proxy_config = nm_device_get_proxy_config(device);
- if (proxy_config)
- dump_proxy_to_props(proxy_config, proxy_builder);
-
- ip4_config = nm_device_get_ip4_config(device);
- if (ip4_config)
- dump_ip_to_props(NM_IP_CONFIG(ip4_config), ip4_builder);
-
- ip6_config = nm_device_get_ip6_config(device);
- if (ip6_config)
- dump_ip_to_props(NM_IP_CONFIG(ip6_config), ip6_builder);
+ l3cd = nm_device_get_l3cd(device, TRUE);
+ if (l3cd) {
+ dump_ip_to_props(l3cd, AF_INET, ip4_builder);
+ dump_ip_to_props(l3cd, AF_INET6, ip6_builder);
+ dump_proxy_to_props(l3cd, proxy_builder);
+ }
dhcp_config = nm_device_get_dhcp_config(device, AF_INET);
if (dhcp_config)
@@ -351,19 +334,16 @@ fill_device_props(NMDevice * device,
}
static void
-fill_vpn_props(NMProxyConfig * proxy_config,
- NMIP4Config * ip4_config,
- NMIP6Config * ip6_config,
- GVariantBuilder *proxy_builder,
- GVariantBuilder *ip4_builder,
- GVariantBuilder *ip6_builder)
+fill_vpn_props(const NML3ConfigData *l3cd,
+ GVariantBuilder * proxy_builder,
+ GVariantBuilder * ip4_builder,
+ GVariantBuilder * ip6_builder)
{
- if (proxy_config)
- dump_proxy_to_props(proxy_config, proxy_builder);
- if (ip4_config)
- dump_ip_to_props(NM_IP_CONFIG(ip4_config), ip4_builder);
- if (ip6_config)
- dump_ip_to_props(NM_IP_CONFIG(ip6_config), ip6_builder);
+ if (l3cd) {
+ dump_ip_to_props(l3cd, AF_INET, ip4_builder);
+ dump_ip_to_props(l3cd, AF_INET6, ip6_builder);
+ dump_proxy_to_props(l3cd, proxy_builder);
+ }
}
static const char *
@@ -479,9 +459,7 @@ _dispatcher_call(NMDispatcherAction action,
gboolean activation_type_external,
NMConnectivityState connectivity_state,
const char * vpn_iface,
- NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config,
+ const NML3ConfigData *l3cd,
NMDispatcherFunc callback,
gpointer user_data,
NMDispatcherCallId ** out_call_id)
@@ -593,13 +571,8 @@ _dispatcher_call(NMDispatcherAction action,
&device_ip6_props,
&device_dhcp4_props,
&device_dhcp6_props);
- if (vpn_ip4_config || vpn_ip6_config) {
- fill_vpn_props(vpn_proxy_config,
- vpn_ip4_config,
- vpn_ip6_config,
- &vpn_proxy_props,
- &vpn_ip4_props,
- &vpn_ip6_props);
+ if (l3cd) {
+ fill_vpn_props(l3cd, &vpn_proxy_props, &vpn_ip4_props, &vpn_ip6_props);
}
}
@@ -693,8 +666,6 @@ nm_dispatcher_call_hostname(NMDispatcherFunc callback,
NM_CONNECTIVITY_UNKNOWN,
NULL,
NULL,
- NULL,
- NULL,
callback,
user_data,
out_call_id);
@@ -744,8 +715,6 @@ nm_dispatcher_call_device(NMDispatcherAction action,
NM_CONNECTIVITY_UNKNOWN,
NULL,
NULL,
- NULL,
- NULL,
callback,
user_data,
out_call_id);
@@ -790,8 +759,6 @@ nm_dispatcher_call_device_sync(NMDispatcherAction action,
NULL,
NULL,
NULL,
- NULL,
- NULL,
NULL);
}
@@ -802,9 +769,7 @@ nm_dispatcher_call_device_sync(NMDispatcherAction action,
* @applied_connection: the currently applied connection
* @parent_device: the parent #NMDevice of the VPN connection
* @vpn_iface: the IP interface of the VPN tunnel, if any
- * @vpn_proxy_config: the #NMProxyConfig of the VPN connection
- * @vpn_ip4_config: the #NMIP4Config of the VPN connection
- * @vpn_ip6_config: the #NMIP6Config of the VPN connection
+ * @vpn_l3cd: the #NML3ConfigData of the VPN connection
* @callback: a caller-supplied callback to execute when done
* @user_data: caller-supplied pointer passed to @callback
* @out_call_id: on success, a call identifier which can be passed to
@@ -821,9 +786,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
NMConnection * applied_connection,
NMDevice * parent_device,
const char * vpn_iface,
- NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config,
+ const NML3ConfigData *l3cd,
NMDispatcherFunc callback,
gpointer user_data,
NMDispatcherCallId ** out_call_id)
@@ -836,9 +799,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
FALSE,
NM_CONNECTIVITY_UNKNOWN,
vpn_iface,
- vpn_proxy_config,
- vpn_ip4_config,
- vpn_ip6_config,
+ l3cd,
callback,
user_data,
out_call_id);
@@ -851,9 +812,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
* @applied_connection: the currently applied connection
* @parent_device: the parent #NMDevice of the VPN connection
* @vpn_iface: the IP interface of the VPN tunnel, if any
- * @vpn_proxy_config: the #NMProxyConfig of the VPN connection
- * @vpn_ip4_config: the #NMIP4Config of the VPN connection
- * @vpn_ip6_config: the #NMIP6Config of the VPN connection
+ * @vpn_l3cd: the #NML3ConfigData of the VPN connection
*
* This method always invokes the dispatcher action synchronously and it may
* take a long time to return.
@@ -866,9 +825,7 @@ nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
NMConnection * applied_connection,
NMDevice * parent_device,
const char * vpn_iface,
- NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config)
+ const NML3ConfigData *l3cd)
{
return _dispatcher_call(action,
TRUE,
@@ -878,9 +835,7 @@ nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
FALSE,
NM_CONNECTIVITY_UNKNOWN,
vpn_iface,
- vpn_proxy_config,
- vpn_ip4_config,
- vpn_ip6_config,
+ l3cd,
NULL,
NULL,
NULL);
@@ -913,8 +868,6 @@ nm_dispatcher_call_connectivity(NMConnectivityState connectivity_state,
connectivity_state,
NULL,
NULL,
- NULL,
- NULL,
callback,
user_data,
out_call_id);
diff --git a/src/core/nm-dispatcher.h b/src/core/nm-dispatcher.h
index 8e4f01cb62..c347352a2d 100644
--- a/src/core/nm-dispatcher.h
+++ b/src/core/nm-dispatcher.h
@@ -51,9 +51,7 @@ gboolean nm_dispatcher_call_vpn(NMDispatcherAction action,
NMConnection * applied_connection,
NMDevice * parent_device,
const char * vpn_iface,
- NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config,
+ const NML3ConfigData *l3cd,
NMDispatcherFunc callback,
gpointer user_data,
NMDispatcherCallId ** out_call_id);
@@ -63,9 +61,7 @@ gboolean nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
NMConnection * applied_connection,
NMDevice * parent_device,
const char * vpn_iface,
- NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config);
+ const NML3ConfigData *l3cd);
gboolean nm_dispatcher_call_connectivity(NMConnectivityState state,
NMDispatcherFunc callback,
diff --git a/src/core/nm-iface-helper.c b/src/core/nm-iface-helper.c
index 83ae1b5466..7dd33d1a5b 100644
--- a/src/core/nm-iface-helper.c
+++ b/src/core/nm-iface-helper.c
@@ -89,6 +89,9 @@ static struct {
NULL, \
"iface-helper: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) _NM_UTILS_MACRO_REST(__VA_ARGS__))
+//XXX
+#if 0
+
/*****************************************************************************/
static void
@@ -100,7 +103,8 @@ _dhcp_client_notify_cb(NMDhcpClient * client,
NMIP4Config * existing;
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
gs_free_error GError *error = NULL;
- NMIP4Config * ip4_config;
+
+ /* FIXME(l3cfg): fix handling metric_any/table_any for routes. */
if (!notify_data || notify_data->notify_type != NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED)
g_return_if_reached();
@@ -508,10 +512,13 @@ ip6_address_changed(NMPlatform * platform,
data,
nm_g_slice_free_fcn(DadFailedHandleData));
}
+#endif
int
main(int argc, char *argv[])
{
+//XXX
+#if 0
char * bad_domains = NULL;
gs_free_error GError *error = NULL;
gboolean wrote_pidfile = FALSE;
@@ -662,8 +669,6 @@ main(int argc, char *argv[])
hwaddr,
bcast_hwaddr,
global_opt.uuid,
- RT_TABLE_MAIN,
- global_opt.priority_v4,
NM_DHCP_CLIENT_FLAGS_NONE,
!!global_opt.dhcp4_hostname,
global_opt.dhcp4_hostname,
@@ -761,6 +766,7 @@ main(int argc, char *argv[])
nm_clear_g_source(&sd_id);
nm_clear_pointer(&gl.main_loop, g_main_loop_unref);
+#endif
return 0;
}
@@ -853,5 +859,6 @@ nm_device_get_type(void)
GType
nm_active_connection_get_type(void)
{
+ (void) gl; //XXX
g_return_val_if_reached(0);
}
diff --git a/src/core/nm-ip-config.c b/src/core/nm-ip-config.c
index 2426eb4941..061c8f2864 100644
--- a/src/core/nm-ip-config.c
+++ b/src/core/nm-ip-config.c
@@ -8,31 +8,126 @@
#include "nm-ip-config.h"
+#include <linux/rtnetlink.h>
+
#include "nm-l3cfg.h"
+#include "NetworkManagerUtils.h"
+
+/*****************************************************************************/
+
+GType nm_ip4_config_get_type(void);
+GType nm_ip6_config_get_type(void);
+
+/*****************************************************************************/
+
+#define NM_IP_CONFIG_ADDRESS_DATA "address-data"
+#define NM_IP_CONFIG_DNS_OPTIONS "dns-options"
+#define NM_IP_CONFIG_DNS_PRIORITY "dns-priority"
+#define NM_IP_CONFIG_DOMAINS "domains"
+#define NM_IP_CONFIG_GATEWAY "gateway"
+#define NM_IP_CONFIG_ROUTE_DATA "route-data"
+#define NM_IP_CONFIG_SEARCHES "searches"
/*****************************************************************************/
-NM_GOBJECT_PROPERTIES_DEFINE(NMIPConfig, PROP_L3CFG, PROP_IS_VPN, );
+typedef struct _NMIPConfigPrivate NMIPConfigPrivate;
-typedef struct _NMIPConfigPrivate {
- NML3Cfg *l3cfg;
- bool is_vpn : 1;
-} NMIPConfigPrivate;
+NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip,
+ NMIPConfig,
+ PROP_IP_L3CFG,
+ PROP_IP_IS_VPN,
+ PROP_IP_ADDRESS_DATA,
+ PROP_IP_GATEWAY,
+ PROP_IP_ROUTE_DATA,
+ PROP_IP_DOMAINS,
+ PROP_IP_SEARCHES,
+ PROP_IP_DNS_PRIORITY,
+ PROP_IP_DNS_OPTIONS, );
G_DEFINE_ABSTRACT_TYPE(NMIPConfig, nm_ip_config, NM_TYPE_DBUS_OBJECT)
-#define NM_IP_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMIPConfig, NM_IS_IP_CONFIG)
+#define NM_IP_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIPConfig, NM_IS_IP_CONFIG)
+
+/*****************************************************************************/
+
+static void _handle_platform_change(NMIPConfig *self, guint32 obj_type_flags, gboolean is_init);
+static void _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd);
/*****************************************************************************/
static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+_value_set_variant_as(GValue *value, const char *const *strv, guint len)
{
- NMIPConfig * self = NM_IP_CONFIG(object);
- NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
+ if (len > 0) {
+ nm_assert(strv && strv[0]);
+ g_value_set_variant(value, g_variant_new_strv((const char *const *) strv, len));
+ } else
+ g_value_set_variant(value, nm_g_variant_singleton_as());
+}
+
+/*****************************************************************************/
+
+static void
+_l3cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMIPConfig *self)
+{
+ switch (notify_data->notify_type) {
+ case NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED:
+ if (notify_data->l3cd_changed.commited)
+ _handle_l3cd_changed(self, notify_data->l3cd_changed.l3cd_new);
+ break;
+ case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE:
+ _handle_platform_change(self, notify_data->platform_change_on_idle.obj_type_flags, FALSE);
+ break;
+ default:
+ break;
+ }
+}
+
+/*****************************************************************************/
+
+static void
+get_property_ip(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ NMIPConfig * self = NM_IP_CONFIG(object);
+ NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
+ const int addr_family = nm_ip_config_get_addr_family(self);
+ char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN];
+ const char *const *strv;
+ guint len;
+ int v_i;
- (void) priv;
switch (prop_id) {
+ case PROP_IP_ADDRESS_DATA:
+ g_value_set_variant(value, priv->v_address_data);
+ break;
+ case PROP_IP_GATEWAY:
+ g_value_set_variant(
+ value,
+ nm_ip_addr_is_null(addr_family, &priv->v_gateway.addr)
+ ? nm_g_variant_singleton_s_empty()
+ : g_variant_new_string(
+ nm_utils_inet_ntop(addr_family, &priv->v_gateway.addr, sbuf_addr)));
+ break;
+ case PROP_IP_ROUTE_DATA:
+ g_value_set_variant(value, priv->v_route_data);
+ break;
+ case PROP_IP_DOMAINS:
+ strv = nm_l3_config_data_get_domains(priv->l3cd, addr_family, &len);
+ _value_set_variant_as(value, strv, len);
+ break;
+ case PROP_IP_SEARCHES:
+ strv = nm_l3_config_data_get_searches(priv->l3cd, addr_family, &len);
+ _value_set_variant_as(value, strv, len);
+ break;
+ case PROP_IP_DNS_PRIORITY:
+ v_i = nm_l3_config_data_get_dns_priority_or_default(priv->l3cd, addr_family);
+ g_value_set_variant(value,
+ (v_i == 0) ? nm_g_variant_singleton_i_0() : g_variant_new_int32(v_i));
+ break;
+ case PROP_IP_DNS_OPTIONS:
+ strv = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len);
+ _value_set_variant_as(value, strv, len);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@@ -44,14 +139,16 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
{
NMIPConfig * self = NM_IP_CONFIG(object);
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
+ gpointer ptr;
switch (prop_id) {
- case PROP_L3CFG:
+ case PROP_IP_L3CFG:
/* construct-only */
- priv->l3cfg = nm_g_object_ref(g_value_get_pointer(value));
- nm_assert(!priv->l3cfg || NM_IS_L3CFG(priv->l3cfg));
+ ptr = g_value_get_pointer(value);
+ nm_assert(NM_IS_L3CFG(ptr));
+ priv->l3cfg = g_object_ref(ptr);
break;
- case PROP_IS_VPN:
+ case PROP_IP_IS_VPN:
/* construct-only */
priv->is_vpn = g_value_get_boolean(value);
break;
@@ -65,13 +162,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
static void
nm_ip_config_init(NMIPConfig *self)
-{
- NMIPConfigPrivate *priv;
-
- priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_IP_CONFIG, NMIPConfigPrivate);
-
- self->_priv = priv;
-}
+{}
NMIPConfig *
nm_ip_config_new(int addr_family, NML3Cfg *l3cfg, gboolean is_vpn)
@@ -89,12 +180,46 @@ nm_ip_config_new(int addr_family, NML3Cfg *l3cfg, gboolean is_vpn)
}
static void
+constructed(GObject *object)
+{
+ NMIPConfig * self = NM_IP_CONFIG(object);
+ NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
+
+ priv->l3cfg_notify_id =
+ g_signal_connect(priv->l3cfg, NM_L3CFG_SIGNAL_NOTIFY, G_CALLBACK(_l3cfg_notify_cb), self);
+
+ priv->l3cd = nm_l3_config_data_ref(nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE));
+
+ _handle_platform_change(self, ~((guint32) 0u), TRUE);
+
+ G_OBJECT_CLASS(nm_ip_config_parent_class)->constructed(object);
+}
+
+void
+nm_ip_config_take_and_unexport_on_idle(NMIPConfig *self_take)
+{
+ if (self_take)
+ nm_dbus_object_unexport_on_idle(g_steal_pointer(&self_take));
+}
+
+static void
finalize(GObject *object)
{
NMIPConfig * self = NM_IP_CONFIG(object);
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
- nm_g_object_unref(priv->l3cfg);
+ nm_clear_g_signal_handler(priv->l3cfg, &priv->l3cfg_notify_id);
+
+ g_object_unref(priv->l3cfg);
+
+ nm_g_variant_unref(priv->v_address_data);
+ nm_g_variant_unref(priv->v_addresses);
+ nm_g_variant_unref(priv->v_route_data);
+ nm_g_variant_unref(priv->v_routes);
+
+ nmp_object_unref(priv->v_gateway.best_default_route);
+
+ nm_l3_config_data_unref(priv->l3cd);
G_OBJECT_CLASS(nm_ip_config_parent_class)->finalize(object);
}
@@ -102,26 +227,617 @@ finalize(GObject *object)
static void
nm_ip_config_class_init(NMIPConfigClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
-
- g_type_class_add_private(object_class, sizeof(NMIPConfigPrivate));
+ GObjectClass * object_class = G_OBJECT_CLASS(klass);
+ NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
- object_class->get_property = get_property;
+ object_class->get_property = get_property_ip;
object_class->set_property = set_property;
+ object_class->constructed = constructed;
object_class->finalize = finalize;
- obj_properties[PROP_L3CFG] =
+ dbus_object_class->export_on_construction = TRUE;
+
+ obj_properties_ip[PROP_IP_L3CFG] =
g_param_spec_pointer(NM_IP_CONFIG_L3CFG,
"",
"",
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IS_VPN] =
+ obj_properties_ip[PROP_IP_IS_VPN] =
g_param_spec_boolean(NM_IP_CONFIG_IS_VPN,
"",
"",
FALSE,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+ obj_properties_ip[PROP_IP_ADDRESS_DATA] =
+ g_param_spec_variant(NM_IP_CONFIG_ADDRESS_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("aa{sv}"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip[PROP_IP_GATEWAY] =
+ g_param_spec_variant(NM_IP_CONFIG_GATEWAY,
+ "",
+ "",
+ G_VARIANT_TYPE("s"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip[PROP_IP_ROUTE_DATA] =
+ g_param_spec_variant(NM_IP_CONFIG_ROUTE_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("aa{sv}"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip[PROP_IP_DOMAINS] =
+ g_param_spec_variant(NM_IP_CONFIG_DOMAINS,
+ "",
+ "",
+ G_VARIANT_TYPE("as"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip[PROP_IP_SEARCHES] =
+ g_param_spec_variant(NM_IP_CONFIG_SEARCHES,
+ "",
+ "",
+ G_VARIANT_TYPE("as"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip[PROP_IP_DNS_PRIORITY] =
+ g_param_spec_variant(NM_IP_CONFIG_DNS_PRIORITY,
+ "",
+ "",
+ G_VARIANT_TYPE("i"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip[PROP_IP_DNS_OPTIONS] =
+ g_param_spec_variant(NM_IP_CONFIG_DNS_OPTIONS,
+ "",
+ "",
+ G_VARIANT_TYPE("as"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST_ip, obj_properties_ip);
+}
+
+/*****************************************************************************/
+
+/* public */
+#define NM_IP4_CONFIG_NAMESERVER_DATA "nameserver-data"
+#define NM_IP4_CONFIG_WINS_SERVER_DATA "wins-server-data"
+
+/* deprecated */
+#define NM_IP4_CONFIG_ADDRESSES "addresses"
+#define NM_IP4_CONFIG_NAMESERVERS "nameservers"
+#define NM_IP4_CONFIG_ROUTES "routes"
+#define NM_IP4_CONFIG_WINS_SERVERS "wins-servers"
+
+typedef struct _NMIP4Config NMIP4Config;
+typedef struct _NMIP4ConfigClass NMIP4ConfigClass;
+
+NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip4,
+ NMIP4Config,
+ PROP_IP4_ADDRESSES,
+ PROP_IP4_NAMESERVERS,
+ PROP_IP4_NAMESERVER_DATA,
+ PROP_IP4_ROUTES,
+ PROP_IP4_WINS_SERVERS,
+ PROP_IP4_WINS_SERVER_DATA, );
+
+struct _NMIP4Config {
+ NMIPConfig parent;
+};
+
+struct _NMIP4ConfigClass {
+ NMIPConfigClass parent;
+};
+
+G_DEFINE_TYPE(NMIP4Config, nm_ip4_config, NM_TYPE_IP_CONFIG)
+
+static void
+get_property_ip4(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ NMIPConfig * self = NM_IP_CONFIG(object);
+ NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
+ char addr_str[NM_UTILS_INET_ADDRSTRLEN];
+ GVariantBuilder builder;
+ const in_addr_t * addrs;
+ guint len;
+ guint i;
+
+ switch (prop_id) {
+ case PROP_IP4_ADDRESSES:
+ g_value_set_variant(value, priv->v_addresses);
+ break;
+ case PROP_IP4_ROUTES:
+ g_value_set_variant(value, priv->v_routes);
+ break;
+ case PROP_IP4_NAMESERVERS:
+ addrs = nm_l3_config_data_get_nameservers(priv->l3cd, AF_INET, &len);
+ g_value_set_variant(value,
+ (len == 0) ? nm_g_variant_singleton_au()
+ : nm_g_variant_new_au(addrs, len));
+ break;
+ case PROP_IP4_NAMESERVER_DATA:
+ addrs = nm_l3_config_data_get_nameservers(priv->l3cd, AF_INET, &len);
+ if (len == 0)
+ g_value_set_variant(value, nm_g_variant_singleton_aaLsvI());
+ else {
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+ for (i = 0; i < len; i++) {
+ GVariantBuilder nested_builder;
+
+ _nm_utils_inet4_ntop(addrs[i], addr_str);
+
+ g_variant_builder_init(&nested_builder, G_VARIANT_TYPE("a{sv}"));
+ g_variant_builder_add(&nested_builder,
+ "{sv}",
+ "address",
+ g_variant_new_string(addr_str));
+ g_variant_builder_add(&builder, "a{sv}", &nested_builder);
+ }
+
+ g_value_take_variant(value, g_variant_builder_end(&builder));
+ }
+ break;
+ case PROP_IP4_WINS_SERVERS:
+ addrs = nm_l3_config_data_get_wins(priv->l3cd, &len);
+ g_value_set_variant(value,
+ (len == 0) ? nm_g_variant_singleton_au()
+ : nm_g_variant_new_au(addrs, len));
+ break;
+ case PROP_IP4_WINS_SERVER_DATA:
+ addrs = nm_l3_config_data_get_wins(priv->l3cd, &len);
+ if (len == 0)
+ g_value_set_variant(value, nm_g_variant_singleton_as());
+ else {
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
+ for (i = 0; i < len; i++)
+ g_variant_builder_add(&builder, "s", _nm_utils_inet4_ntop(addrs[i], addr_str));
+ g_value_take_variant(value, g_variant_builder_end(&builder));
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static const NMDBusInterfaceInfoExtended interface_info_ip4_config = {
+ .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
+ NM_DBUS_INTERFACE_IP4_CONFIG,
+ .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses",
+ "aau",
+ NM_IP4_CONFIG_ADDRESSES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
+ "aa{sv}",
+ NM_IP_CONFIG_ADDRESS_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP_CONFIG_GATEWAY),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes", "aau", NM_IP4_CONFIG_ROUTES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData",
+ "aa{sv}",
+ NM_IP_CONFIG_ROUTE_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NameserverData",
+ "aa{sv}",
+ NM_IP4_CONFIG_NAMESERVER_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers",
+ "au",
+ NM_IP4_CONFIG_NAMESERVERS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP_CONFIG_DOMAINS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches", "as", NM_IP_CONFIG_SEARCHES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions",
+ "as",
+ NM_IP_CONFIG_DNS_OPTIONS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority",
+ "i",
+ NM_IP_CONFIG_DNS_PRIORITY),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServerData",
+ "as",
+ NM_IP4_CONFIG_WINS_SERVER_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServers",
+ "au",
+ NM_IP4_CONFIG_WINS_SERVERS), ), ),
+};
+
+static void
+nm_ip4_config_init(NMIP4Config *self)
+{}
+
+static void
+nm_ip4_config_class_init(NMIP4ConfigClass *klass)
+{
+ GObjectClass * object_class = G_OBJECT_CLASS(klass);
+ NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
+ NMIPConfigClass * ip_config_class = NM_IP_CONFIG_CLASS(klass);
+
+ ip_config_class->addr_family = AF_INET;
+
+ dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/IP4Config");
+ dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_ip4_config);
+
+ object_class->get_property = get_property_ip4;
+
+ obj_properties_ip4[PROP_IP4_ADDRESSES] =
+ g_param_spec_variant(NM_IP4_CONFIG_ADDRESSES,
+ "",
+ "",
+ G_VARIANT_TYPE("aau"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_ROUTES] =
+ g_param_spec_variant(NM_IP4_CONFIG_ROUTES,
+ "",
+ "",
+ G_VARIANT_TYPE("aau"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_NAMESERVER_DATA] =
+ g_param_spec_variant(NM_IP4_CONFIG_NAMESERVER_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("aa{sv}"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_NAMESERVERS] =
+ g_param_spec_variant(NM_IP4_CONFIG_NAMESERVERS,
+ "",
+ "",
+ G_VARIANT_TYPE("au"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_WINS_SERVER_DATA] =
+ g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVER_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("as"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_WINS_SERVERS] =
+ g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVERS,
+ "",
+ "",
+ G_VARIANT_TYPE("au"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST_ip4, obj_properties_ip4);
+}
+
+/*****************************************************************************/
+
+/* public */
+#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
+
+/* deprecated */
+#define NM_IP6_CONFIG_ADDRESSES "addresses"
+#define NM_IP6_CONFIG_ROUTES "routes"
+
+typedef struct _NMIP6Config NMIP6Config;
+typedef struct _NMIP6ConfigClass NMIP6ConfigClass;
+
+NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip6,
+ NMIP6Config,
+ PROP_IP6_NAMESERVERS,
+ PROP_IP6_ADDRESSES,
+ PROP_IP6_ROUTES, );
+
+struct _NMIP6Config {
+ NMIPConfig parent;
+};
+
+struct _NMIP6ConfigClass {
+ NMIPConfigClass parent;
+};
+
+G_DEFINE_TYPE(NMIP6Config, nm_ip6_config, NM_TYPE_IP_CONFIG)
+
+static const NMDBusInterfaceInfoExtended interface_info_ip6_config = {
+ .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
+ NM_DBUS_INTERFACE_IP6_CONFIG,
+ .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses",
+ "a(ayuay)",
+ NM_IP6_CONFIG_ADDRESSES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
+ "aa{sv}",
+ NM_IP_CONFIG_ADDRESS_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP_CONFIG_GATEWAY),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes",
+ "a(ayuayu)",
+ NM_IP6_CONFIG_ROUTES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData",
+ "aa{sv}",
+ NM_IP_CONFIG_ROUTE_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers",
+ "aay",
+ NM_IP6_CONFIG_NAMESERVERS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP_CONFIG_DOMAINS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches", "as", NM_IP_CONFIG_SEARCHES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions",
+ "as",
+ NM_IP_CONFIG_DNS_OPTIONS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority",
+ "i",
+ NM_IP_CONFIG_DNS_PRIORITY), ), ),
+};
+
+static void
+get_property_ip6(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ NMIPConfig * self = NM_IP_CONFIG(object);
+ NMIPConfigPrivate * priv = NM_IP_CONFIG_GET_PRIVATE(self);
+ GVariantBuilder builder;
+ guint len;
+ guint i;
+ const struct in6_addr *addrs;
+
+ switch (prop_id) {
+ case PROP_IP6_ADDRESSES:
+ g_value_set_variant(value, priv->v_addresses);
+ break;
+ case PROP_IP6_ROUTES:
+ g_value_set_variant(value, priv->v_routes);
+ break;
+ case PROP_IP6_NAMESERVERS:
+ addrs = nm_l3_config_data_get_nameservers(priv->l3cd, AF_INET6, &len);
+ if (len == 0)
+ g_value_set_variant(value, nm_g_variant_singleton_aay());
+ else {
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("aay"));
+ for (i = 0; i < len; i++)
+ g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&addrs[i]));
+ g_value_take_variant(value, g_variant_builder_end(&builder));
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_ip6_config_init(NMIP6Config *self)
+{}
+
+static void
+nm_ip6_config_class_init(NMIP6ConfigClass *klass)
+{
+ GObjectClass * object_class = G_OBJECT_CLASS(klass);
+ NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
+ NMIPConfigClass * ip_config_class = NM_IP_CONFIG_CLASS(klass);
+
+ ip_config_class->addr_family = AF_INET6;
+
+ dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/IP6Config");
+ dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_ip6_config);
+
+ object_class->get_property = get_property_ip6;
+
+ obj_properties_ip6[PROP_IP6_ADDRESSES] =
+ g_param_spec_variant(NM_IP6_CONFIG_ADDRESSES,
+ "",
+ "",
+ G_VARIANT_TYPE("a(ayuay)"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_ROUTES] =
+ g_param_spec_variant(NM_IP6_CONFIG_ROUTES,
+ "",
+ "",
+ G_VARIANT_TYPE("a(ayuayu)"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_NAMESERVERS] =
+ g_param_spec_variant(NM_IP6_CONFIG_NAMESERVERS,
+ "",
+ "",
+ G_VARIANT_TYPE("aay"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST_ip6, obj_properties_ip6);
+}
+
+/*****************************************************************************/
+
+#define _notify_all(self, changed_params, n_changed_params) \
+ G_STMT_START \
+ { \
+ NMIPConfig *const _self = (self); \
+ const guint _n_changed_params = (n_changed_params); \
+ GParamSpec *const *const _changed_params = (changed_params); \
+ guint _i; \
+ \
+ if (_n_changed_params > 0) { \
+ nm_assert(_n_changed_params <= G_N_ELEMENTS(changed_params)); \
+ if (_n_changed_params > 1) \
+ g_object_freeze_notify(G_OBJECT(_self)); \
+ for (_i = 0; _i < _n_changed_params; _i++) \
+ g_object_notify_by_pspec(G_OBJECT(_self), _changed_params[_i]); \
+ if (_n_changed_params > 1) \
+ g_object_thaw_notify(G_OBJECT(_self)); \
+ } \
+ } \
+ G_STMT_END
+
+static void
+_handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd)
+{
+ const int addr_family = nm_ip_config_get_addr_family(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMIPConfigPrivate * priv = NM_IP_CONFIG_GET_PRIVATE(self);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
+ GParamSpec * changed_params[8];
+ guint n_changed_params = 0;
+ const char *const * strv;
+ const char *const * strv_old;
+ gconstpointer addrs;
+ gconstpointer addrs_old;
+ guint len;
+ guint len_old;
+ int v_i;
+ int v_i_old;
+
+ l3cd_old = g_steal_pointer(&priv->l3cd);
+ priv->l3cd = nm_l3_config_data_ref(l3cd);
+
+ addrs_old = nm_l3_config_data_get_nameservers(l3cd_old, addr_family, &len_old);
+ addrs = nm_l3_config_data_get_nameservers(priv->l3cd, addr_family, &len);
+ if (!nm_memeq_n(addrs_old, len_old, addrs, len, nm_utils_addr_family_to_size(addr_family))) {
+ if (IS_IPv4) {
+ changed_params[n_changed_params++] = obj_properties_ip4[PROP_IP4_NAMESERVER_DATA];
+ changed_params[n_changed_params++] = obj_properties_ip4[PROP_IP4_NAMESERVERS];
+ } else
+ changed_params[n_changed_params++] = obj_properties_ip6[PROP_IP6_NAMESERVERS];
+ }
+
+ strv_old = nm_l3_config_data_get_domains(l3cd_old, addr_family, &len_old);
+ strv = nm_l3_config_data_get_domains(priv->l3cd, addr_family, &len);
+ if (!nm_strv_equal_n(strv, len, strv_old, len_old))
+ changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DOMAINS];
+
+ strv_old = nm_l3_config_data_get_searches(l3cd_old, addr_family, &len_old);
+ strv = nm_l3_config_data_get_searches(priv->l3cd, addr_family, &len);
+ if (!nm_strv_equal_n(strv, len, strv_old, len_old))
+ changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_SEARCHES];
+
+ v_i_old = nm_l3_config_data_get_dns_priority_or_default(l3cd_old, addr_family);
+ v_i = nm_l3_config_data_get_dns_priority_or_default(priv->l3cd, addr_family);
+ if (v_i != v_i_old)
+ changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_PRIORITY];
+
+ strv_old = nm_l3_config_data_get_dns_options(l3cd_old, addr_family, &len);
+ strv = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len);
+ if (!nm_strv_equal_n(strv, len, strv_old, len_old))
+ changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_OPTIONS];
+
+ if (IS_IPv4) {
+ addrs_old = nm_l3_config_data_get_wins(l3cd_old, &len_old);
+ addrs = nm_l3_config_data_get_wins(priv->l3cd, &len);
+ if (!nm_memeq_n(addrs_old, len_old, addrs, len, sizeof(in_addr_t))) {
+ changed_params[n_changed_params++] = obj_properties_ip4[PROP_IP4_WINS_SERVER_DATA];
+ changed_params[n_changed_params++] = obj_properties_ip4[PROP_IP4_WINS_SERVERS];
+ }
+ }
+
+ _notify_all(self, changed_params, n_changed_params);
+}
+
+static void
+_handle_platform_change(NMIPConfig *self, guint32 obj_type_flags, gboolean is_init)
+{
+ const int addr_family = nm_ip_config_get_addr_family(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMIPConfigPrivate * priv = NM_IP_CONFIG_GET_PRIVATE(self);
+ GParamSpec * changed_params[5];
+ guint n_changed_params = 0;
+ const NMDedupMultiHeadEntry *head_entry_routes = NULL;
+ gboolean best_default_route_changed = FALSE;
+
+ if (NM_FLAGS_ANY(obj_type_flags,
+ (nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4))
+ | nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))))) {
+ const NMPObject *best_default_route = NULL;
+
+ head_entry_routes = nm_platform_lookup_object(nm_l3cfg_get_platform(priv->l3cfg),
+ NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4),
+ nm_l3cfg_get_ifindex(priv->l3cfg));
+ if (head_entry_routes) {
+ NMDedupMultiIter iter;
+ const NMPObject *obj;
+
+ nm_dedup_multi_iter_init(&iter, head_entry_routes);
+ while (nm_platform_dedup_multi_iter_next_obj(&iter,
+ &obj,
+ NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))) {
+ const NMPlatformIPXRoute *r = NMP_OBJECT_CAST_IPX_ROUTE(obj);
+
+ /* Determine the gateway. That is the next hop of a route
+ * - 0.0.0.0/0 or ::/0
+ * - type=unicast
+ * - table=main
+ */
+ if (r->rx.plen != 0
+ || r->rx.type_coerced != nm_platform_route_type_coerce(RTN_UNICAST)
+ || r->rx.table_coerced != nm_platform_route_table_coerce(RT_TABLE_MAIN)
+ || !nm_ip_addr_is_null(addr_family, r->rx.network_ptr))
+ continue;
+
+ if (!best_default_route
+ || NMP_OBJECT_CAST_IP_ROUTE(best_default_route)->metric > r->rx.metric)
+ best_default_route = obj;
+ }
+ }
+
+ if (nmp_object_ref_set(&priv->v_gateway.best_default_route, best_default_route)) {
+ gconstpointer gateway_next_hop;
+
+ gateway_next_hop = priv->v_gateway.best_default_route
+ ? nm_platform_ip_route_get_gateway(
+ addr_family,
+ NMP_OBJECT_CAST_IP_ROUTE(priv->v_gateway.best_default_route))
+ : &nm_ip_addr_zero;
+ if (!nm_ip_addr_equal(addr_family, &priv->v_gateway.addr, gateway_next_hop)) {
+ nm_ip_addr_set(addr_family, &priv->v_gateway.addr, gateway_next_hop);
+ best_default_route_changed = TRUE;
+ }
+ }
+ }
+
+ if (best_default_route_changed
+ || NM_FLAGS_ANY(obj_type_flags,
+ nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)))) {
+ gs_unref_variant GVariant *x_address_data = NULL;
+ gs_unref_variant GVariant *x_addresses = NULL;
+
+ nm_utils_ip_addresses_to_dbus(addr_family,
+ nm_platform_lookup_object(nm_l3cfg_get_platform(priv->l3cfg),
+ NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4),
+ nm_l3cfg_get_ifindex(priv->l3cfg)),
+ priv->v_gateway.best_default_route,
+ &x_address_data,
+ &x_addresses);
+
+ if (!nm_g_variant_equal(priv->v_address_data, x_address_data)) {
+ changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_ADDRESS_DATA];
+ g_variant_ref_sink(x_address_data);
+ NM_SWAP(&priv->v_address_data, &x_address_data);
+ }
+ if (!nm_g_variant_equal(priv->v_addresses, x_addresses)) {
+ changed_params[n_changed_params++] = IS_IPv4 ? obj_properties_ip4[PROP_IP4_ADDRESSES]
+ : obj_properties_ip6[PROP_IP6_ADDRESSES];
+ g_variant_ref_sink(x_addresses);
+ NM_SWAP(&priv->v_addresses, &x_addresses);
+ }
+ }
+
+ if (best_default_route_changed)
+ changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_GATEWAY];
+
+ if (NM_FLAGS_ANY(obj_type_flags, nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)))) {
+ gs_unref_variant GVariant *x_route_data = NULL;
+ gs_unref_variant GVariant *x_routes = NULL;
+
+ nm_utils_ip_routes_to_dbus(addr_family, head_entry_routes, &x_route_data, &x_routes);
+
+ if (!nm_g_variant_equal(priv->v_route_data, x_route_data)) {
+ changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_ROUTE_DATA];
+ g_variant_ref_sink(x_route_data);
+ NM_SWAP(&priv->v_route_data, &x_route_data);
+ }
+ if (!nm_g_variant_equal(priv->v_routes, x_routes)) {
+ changed_params[n_changed_params++] =
+ IS_IPv4 ? obj_properties_ip4[PROP_IP4_ROUTES] : obj_properties_ip6[PROP_IP6_ROUTES];
+ g_variant_ref_sink(x_routes);
+ NM_SWAP(&priv->v_routes, &x_routes);
+ }
+ }
+
+ if (!is_init)
+ _notify_all(self, changed_params, n_changed_params);
}
diff --git a/src/core/nm-ip-config.h b/src/core/nm-ip-config.h
index 8e1a593412..224f180e55 100644
--- a/src/core/nm-ip-config.h
+++ b/src/core/nm-ip-config.h
@@ -7,6 +7,7 @@
#define __NM_IP_CONFIG_H__
#include "nm-dbus-object.h"
+#include "nm-l3cfg.h"
/*****************************************************************************/
@@ -22,23 +23,65 @@
#define NM_IP_CONFIG_L3CFG "l3cfg"
#define NM_IP_CONFIG_IS_VPN "is-vpn"
-struct _NMIPConfigPrivate;
+struct _NMIPConfigPrivate {
+ NML3Cfg * l3cfg;
+ const NML3ConfigData *l3cd;
+ GVariant * v_address_data;
+ GVariant * v_addresses;
+ GVariant * v_route_data;
+ GVariant * v_routes;
+ struct {
+ const NMPObject *best_default_route;
+ NMIPAddr addr;
+ } v_gateway;
+ gulong l3cfg_notify_id;
+ bool is_vpn : 1;
+};
struct _NMIPConfig {
- NMDBusObject parent;
- struct _NMIPConfigPrivate *_priv;
+ NMDBusObject parent;
+ struct _NMIPConfigPrivate _priv;
};
typedef struct {
NMDBusObjectClass parent;
- gboolean is_ipv4;
int addr_family;
} NMIPConfigClass;
GType nm_ip_config_get_type(void);
-GType nm_ip4_config_get_type(void);
-GType nm_ip6_config_get_type(void);
NMIPConfig *nm_ip_config_new(int addr_family, NML3Cfg *l3cfg, gboolean is_vpn);
+void nm_ip_config_take_and_unexport_on_idle(NMIPConfig *self_take);
+
+/*****************************************************************************/
+
+static inline NML3Cfg *
+nm_ip_config_get_l3cfg(NMIPConfig *self)
+{
+ g_return_val_if_fail(NM_IS_IP_CONFIG(self), NULL);
+
+ return self->_priv.l3cfg;
+}
+
+static inline struct _NMDedupMultiIndex *
+nm_ip_config_get_multi_index(NMIPConfig *self)
+{
+ return nm_l3cfg_get_multi_idx(nm_ip_config_get_l3cfg(self));
+}
+
+static inline int
+nm_ip_config_get_ifindex(NMIPConfig *self)
+{
+ return nm_l3cfg_get_ifindex(nm_ip_config_get_l3cfg(self));
+}
+
+static inline int
+nm_ip_config_get_addr_family(NMIPConfig *self)
+{
+ g_return_val_if_fail(NM_IS_IP_CONFIG(self), AF_UNSPEC);
+
+ return NM_IP_CONFIG_GET_CLASS(self)->addr_family;
+}
+
#endif /* __NM_IP_CONFIG_H__ */
diff --git a/src/core/nm-ip4-config.c b/src/core/nm-ip4-config.c
deleted file mode 100644
index a622b05379..0000000000
--- a/src/core/nm-ip4-config.c
+++ /dev/null
@@ -1,3303 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2005 - 2017 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "nm-ip4-config.h"
-
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <linux/rtnetlink.h>
-
-#include "libnm-glib-aux/nm-dedup-multi.h"
-
-#include "nm-utils.h"
-#include "libnm-platform/nmp-object.h"
-#include "libnm-platform/nm-platform.h"
-#include "libnm-platform/nm-platform-utils.h"
-#include "NetworkManagerUtils.h"
-#include "libnm-core-intern/nm-core-internal.h"
-#include "nm-dbus-object.h"
-
-/*****************************************************************************/
-
-/* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */
-G_STATIC_ASSERT(sizeof(uint) >= sizeof(guint32));
-G_STATIC_ASSERT(G_MAXUINT >= 0xFFFFFFFF);
-
-/*****************************************************************************/
-
-static gboolean
-_route_valid(const NMPlatformIP4Route *r)
-{
- return r && r->plen <= 32
- && r->network == nm_utils_ip4_address_clear_host_address(r->network, r->plen);
-}
-
-/*****************************************************************************/
-
-static void
-_idx_obj_id_hash_update(const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj,
- NMHashState * h)
-{
- nmp_object_id_hash_update((NMPObject *) obj, h);
-}
-
-static gboolean
-_idx_obj_id_equal(const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj_a,
- const NMDedupMultiObj * obj_b)
-{
- return nmp_object_id_equal((NMPObject *) obj_a, (NMPObject *) obj_b);
-}
-
-void
-nm_ip_config_dedup_multi_idx_type_init(NMIPConfigDedupMultiIdxType *idx_type,
- NMPObjectType obj_type)
-{
- static const NMDedupMultiIdxTypeClass idx_type_class = {
- .idx_obj_id_hash_update = _idx_obj_id_hash_update,
- .idx_obj_id_equal = _idx_obj_id_equal,
- };
-
- nm_dedup_multi_idx_type_init((NMDedupMultiIdxType *) idx_type, &idx_type_class);
- idx_type->obj_type = obj_type;
-}
-
-/*****************************************************************************/
-
-gboolean
-_nm_ip_config_add_obj(NMDedupMultiIndex * multi_idx,
- NMIPConfigDedupMultiIdxType *idx_type,
- int ifindex,
- const NMPObject * obj_new,
- const NMPlatformObject * pl_new,
- gboolean merge,
- gboolean append_force,
- const NMPObject ** out_obj_old /* returns a reference! */,
- const NMPObject ** out_obj_new /* does not return a reference */)
-{
- NMPObject obj_new_stackinit;
- const NMDedupMultiEntry *entry_old;
- const NMDedupMultiEntry *entry_new;
-
- nm_assert(multi_idx);
- nm_assert(idx_type);
- nm_assert(NM_IN_SET(idx_type->obj_type,
- NMP_OBJECT_TYPE_IP4_ADDRESS,
- NMP_OBJECT_TYPE_IP4_ROUTE,
- NMP_OBJECT_TYPE_IP6_ADDRESS,
- NMP_OBJECT_TYPE_IP6_ROUTE));
- nm_assert(ifindex > 0);
-
- /* we go through extra lengths to accept a full obj_new object. That one,
- * can be reused by increasing the ref-count. */
- if (!obj_new) {
- nm_assert(pl_new);
- obj_new = nmp_object_stackinit(&obj_new_stackinit, idx_type->obj_type, pl_new);
- NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(&obj_new_stackinit)->ifindex = ifindex;
- } else {
- nm_assert(!pl_new);
- nm_assert(NMP_OBJECT_GET_TYPE(obj_new) == idx_type->obj_type);
- if (NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj_new)->ifindex != ifindex) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(&obj_new_stackinit)->ifindex = ifindex;
- }
- }
- nm_assert(NMP_OBJECT_GET_TYPE(obj_new) == idx_type->obj_type);
- nm_assert(nmp_object_is_alive(obj_new));
-
- entry_old = nm_dedup_multi_index_lookup_obj(multi_idx, &idx_type->parent, obj_new);
-
- if (entry_old) {
- gboolean modified = FALSE;
- const NMPObject *obj_old = entry_old->obj;
-
- if (nmp_object_equal(obj_new, obj_old)) {
- nm_dedup_multi_entry_set_dirty(entry_old, FALSE);
- goto append_force_and_out;
- }
-
- /* if @merge, we merge the new object with the existing one.
- * Otherwise, we replace it entirely. */
- if (merge) {
- switch (idx_type->obj_type) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- /* for addresses that we read from the kernel, we keep the timestamps as defined
- * by the previous source (item_old). The reason is, that the other source configured the lifetimes
- * with "what should be" and the kernel values are "what turned out after configuring it".
- *
- * For other sources, the longer lifetime wins. */
- if ((obj_new->ip_address.addr_source == NM_IP_CONFIG_SOURCE_KERNEL
- && obj_old->ip_address.addr_source != NM_IP_CONFIG_SOURCE_KERNEL)
- || nm_platform_ip_address_cmp_expiry(NMP_OBJECT_CAST_IP_ADDRESS(obj_old),
- NMP_OBJECT_CAST_IP_ADDRESS(obj_new))
- > 0) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_address.timestamp =
- NMP_OBJECT_CAST_IP_ADDRESS(obj_old)->timestamp;
- obj_new_stackinit.ip_address.lifetime =
- NMP_OBJECT_CAST_IP_ADDRESS(obj_old)->lifetime;
- obj_new_stackinit.ip_address.preferred =
- NMP_OBJECT_CAST_IP_ADDRESS(obj_old)->preferred;
- modified = TRUE;
- }
-
- /* keep the maximum addr_source. */
- if (obj_new->ip_address.addr_source < obj_old->ip_address.addr_source) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
- modified = TRUE;
- }
- break;
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- /* keep the maximum rt_source. */
- if (obj_new->ip_route.rt_source < obj_old->ip_route.rt_source) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source;
- modified = TRUE;
- }
- if (!obj_new->ip_route.is_external && obj_old->ip_route.is_external) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_route.is_external = FALSE;
- modified = TRUE;
- }
- break;
- default:
- nm_assert_not_reached();
- break;
- }
-
- if (modified && nmp_object_equal(obj_new, obj_old)) {
- nm_dedup_multi_entry_set_dirty(entry_old, FALSE);
- goto append_force_and_out;
- }
- }
- }
-
- if (!nm_dedup_multi_index_add_full(multi_idx,
- &idx_type->parent,
- obj_new,
- append_force ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE
- : NM_DEDUP_MULTI_IDX_MODE_APPEND,
- NULL,
- entry_old ?: NM_DEDUP_MULTI_ENTRY_MISSING,
- NULL,
- &entry_new,
- out_obj_old)) {
- nm_assert_not_reached();
- NM_SET_OUT(out_obj_new, NULL);
- return FALSE;
- }
-
- NM_SET_OUT(out_obj_new, entry_new->obj);
- return TRUE;
-
-append_force_and_out:
- NM_SET_OUT(out_obj_old, nmp_object_ref(entry_old->obj));
- NM_SET_OUT(out_obj_new, entry_old->obj);
- if (append_force) {
- if (nm_dedup_multi_entry_reorder(entry_old, NULL, TRUE))
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * _nm_ip_config_lookup_ip_route:
- * @multi_idx:
- * @idx_type:
- * @needle:
- * @cmp_type: after lookup, filter the result by comparing with @cmp_type. Only
- * return the result, if it compares equal to @needle according to this @cmp_type.
- * Note that the index uses %NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST type, so passing
- * that compare-type means not to filter any further.
- *
- * Returns: the found entry or %NULL.
- */
-const NMDedupMultiEntry *
-_nm_ip_config_lookup_ip_route(const NMDedupMultiIndex * multi_idx,
- const NMIPConfigDedupMultiIdxType *idx_type,
- const NMPObject * needle,
- NMPlatformIPRouteCmpType cmp_type)
-{
- const NMDedupMultiEntry *entry;
-
- nm_assert(multi_idx);
- nm_assert(idx_type);
- nm_assert(NM_IN_SET(idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
- nm_assert(NMP_OBJECT_GET_TYPE(needle) == idx_type->obj_type);
-
- entry = nm_dedup_multi_index_lookup_obj(multi_idx, &idx_type->parent, needle);
- if (!entry)
- return NULL;
-
- if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) {
- nm_assert((NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP4_ROUTE
- && nm_platform_ip4_route_cmp(NMP_OBJECT_CAST_IP4_ROUTE(entry->obj),
- NMP_OBJECT_CAST_IP4_ROUTE(needle),
- cmp_type)
- == 0)
- || (NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP6_ROUTE
- && nm_platform_ip6_route_cmp(NMP_OBJECT_CAST_IP6_ROUTE(entry->obj),
- NMP_OBJECT_CAST_IP6_ROUTE(needle),
- cmp_type)
- == 0));
- } else {
- if (NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP4_ROUTE) {
- if (nm_platform_ip4_route_cmp(NMP_OBJECT_CAST_IP4_ROUTE(entry->obj),
- NMP_OBJECT_CAST_IP4_ROUTE(needle),
- cmp_type)
- != 0)
- return NULL;
- } else {
- if (nm_platform_ip6_route_cmp(NMP_OBJECT_CAST_IP6_ROUTE(entry->obj),
- NMP_OBJECT_CAST_IP6_ROUTE(needle),
- cmp_type)
- != 0)
- return NULL;
- }
- }
- return entry;
-}
-
-/*****************************************************************************/
-
-NM_GOBJECT_PROPERTIES_DEFINE(NMIP4Config,
- PROP_MULTI_IDX,
- PROP_IFINDEX,
- PROP_ADDRESS_DATA,
- PROP_ADDRESSES,
- PROP_ROUTE_DATA,
- PROP_ROUTES,
- PROP_GATEWAY,
- PROP_NAMESERVER_DATA,
- PROP_NAMESERVERS,
- PROP_DOMAINS,
- PROP_SEARCHES,
- PROP_DNS_OPTIONS,
- PROP_WINS_SERVER_DATA,
- PROP_WINS_SERVERS,
- PROP_DNS_PRIORITY, );
-
-typedef struct {
- bool metered : 1;
- bool never_default : 1;
- guint32 mtu;
- int ifindex;
- NMIPConfigSource mtu_source;
- int dns_priority;
- NMSettingConnectionMdns mdns;
- NMSettingConnectionLlmnr llmnr;
- GArray * nameservers;
- GPtrArray * domains;
- GPtrArray * searches;
- GPtrArray * dns_options;
- GArray * nis;
- char * nis_domain;
- GArray * wins;
- GVariant * address_data_variant;
- GVariant * addresses_variant;
- GVariant * route_data_variant;
- GVariant * routes_variant;
- NMDedupMultiIndex * multi_idx;
- const NMPObject * best_default_route;
- union {
- NMIPConfigDedupMultiIdxType idx_ip4_addresses_;
- NMDedupMultiIdxType idx_ip4_addresses;
- };
- union {
- NMIPConfigDedupMultiIdxType idx_ip4_routes_;
- NMDedupMultiIdxType idx_ip4_routes;
- };
- NMIPConfigFlags config_flags;
-} NMIP4ConfigPrivate;
-
-struct _NMIP4Config {
- NMIPConfig parent;
- NMIP4ConfigPrivate _priv;
-};
-
-struct _NMIP4ConfigClass {
- NMIPConfigClass parent;
-};
-
-G_DEFINE_TYPE(NMIP4Config, nm_ip4_config, NM_TYPE_IP_CONFIG)
-
-#define NM_IP4_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIP4Config, NM_IS_IP4_CONFIG)
-
-/*****************************************************************************/
-
-static void
-_add_address(NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new);
-static void _add_route(NMIP4Config * self,
- const NMPObject *obj_new,
- const NMPlatformIP4Route *new,
- const NMPObject **out_obj_new);
-static const NMDedupMultiEntry *
-_lookup_route(const NMIP4Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type);
-
-/*****************************************************************************/
-
-int
-nm_ip4_config_get_ifindex(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->ifindex;
-}
-
-NMDedupMultiIndex *
-nm_ip4_config_get_multi_idx(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->multi_idx;
-}
-
-/*****************************************************************************/
-
-const NMDedupMultiHeadEntry *
-nm_ip4_config_lookup_addresses(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip4_addresses, NULL);
-}
-
-void
-nm_ip_config_iter_ip4_address_init(NMDedupMultiIter *ipconf_iter, const NMIP4Config *self)
-{
- nm_assert(NM_IS_IP4_CONFIG(self));
-
- nm_dedup_multi_iter_init(ipconf_iter, nm_ip4_config_lookup_addresses(self));
-}
-
-/*****************************************************************************/
-
-const NMDedupMultiHeadEntry *
-nm_ip4_config_lookup_routes(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip4_routes, NULL);
-}
-
-void
-nm_ip_config_iter_ip4_route_init(NMDedupMultiIter *ipconf_iter, const NMIP4Config *self)
-{
- nm_assert(NM_IS_IP4_CONFIG(self));
-
- nm_dedup_multi_iter_init(ipconf_iter, nm_ip4_config_lookup_routes(self));
-}
-
-/*****************************************************************************/
-
-const NMPObject *
-_nm_ip_config_best_default_route_find_better(const NMPObject *obj_cur, const NMPObject *obj_cmp)
-{
- nm_assert(!obj_cur
- || NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_cur),
- NMP_OBJECT_TYPE_IP4_ROUTE,
- NMP_OBJECT_TYPE_IP6_ROUTE));
- nm_assert(!obj_cmp
- || (!obj_cur
- && NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_cmp),
- NMP_OBJECT_TYPE_IP4_ROUTE,
- NMP_OBJECT_TYPE_IP6_ROUTE))
- || NMP_OBJECT_GET_TYPE(obj_cur) == NMP_OBJECT_GET_TYPE(obj_cmp));
- nm_assert(!obj_cur || nmp_object_ip_route_is_best_default_route(obj_cur));
-
- /* assumes that @obj_cur is already the best default route (or NULL). It checks whether
- * @obj_cmp is also a default route and returns the best of both. */
- if (obj_cmp && nmp_object_ip_route_is_best_default_route(obj_cmp)) {
- guint32 metric_cur, metric_cmp;
-
- if (!obj_cur)
- return obj_cmp;
-
- metric_cur = NMP_OBJECT_CAST_IP_ROUTE(obj_cur)->metric;
- metric_cmp = NMP_OBJECT_CAST_IP_ROUTE(obj_cmp)->metric;
-
- if (metric_cmp < metric_cur)
- return obj_cmp;
-
- if (metric_cmp == metric_cur) {
- int c;
-
- /* Routes have the same metric. We still want to deterministically
- * prefer one or the other. It's important to consistently choose one
- * or the other, so that the order doesn't matter how routes are added
- * (and merged). */
- c = nmp_object_cmp(obj_cur, obj_cmp);
- if (c != 0)
- return c < 0 ? obj_cur : obj_cmp;
-
- /* as last resort, compare pointers. */
- if (obj_cmp < obj_cur)
- return obj_cmp;
- }
- }
- return obj_cur;
-}
-
-gboolean
-_nm_ip_config_best_default_route_merge(const NMPObject **best_default_route,
- const NMPObject * new_candidate)
-{
- new_candidate =
- _nm_ip_config_best_default_route_find_better(*best_default_route, new_candidate);
- return nmp_object_ref_set(best_default_route, new_candidate);
-}
-
-const NMPObject *
-nm_ip4_config_best_default_route_get(const NMIP4Config *self)
-{
- g_return_val_if_fail(NM_IS_IP4_CONFIG(self), NULL);
-
- return NM_IP4_CONFIG_GET_PRIVATE(self)->best_default_route;
-}
-
-const NMPObject *
-_nm_ip4_config_best_default_route_find(const NMIP4Config *self)
-{
- NMDedupMultiIter ipconf_iter;
- const NMPObject *new_best_default_route = NULL;
-
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, NULL) {
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route,
- ipconf_iter.current->obj);
- }
- return new_best_default_route;
-}
-
-in_addr_t
-nmtst_ip4_config_get_gateway(NMIP4Config *config)
-{
- const NMPObject *rt;
-
- g_assert(NM_IS_IP4_CONFIG(config));
-
- rt = nm_ip4_config_best_default_route_get(config);
- if (!rt)
- return 0;
- return NMP_OBJECT_CAST_IP4_ROUTE(rt)->gateway;
-}
-
-/*****************************************************************************/
-
-static void
-_notify_addresses(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nm_clear_g_variant(&priv->address_data_variant);
- nm_clear_g_variant(&priv->addresses_variant);
- nm_gobject_notify_together(self, PROP_ADDRESS_DATA, PROP_ADDRESSES);
-}
-
-static void
-_notify_routes(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nm_assert(priv->best_default_route == _nm_ip4_config_best_default_route_find(self));
- nm_clear_g_variant(&priv->route_data_variant);
- nm_clear_g_variant(&priv->routes_variant);
- nm_gobject_notify_together(self, PROP_ROUTE_DATA, PROP_ROUTES);
-}
-
-/*****************************************************************************/
-
-NMIP4Config *
-nm_ip4_config_clone(const NMIP4Config *self)
-{
- NMIP4Config *copy;
-
- copy = nm_ip4_config_new(nm_ip4_config_get_multi_idx(self), -1);
- nm_ip4_config_replace(copy, self, NULL);
-
- return copy;
-}
-
-NMIP4Config *
-nm_ip4_config_capture(NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex)
-{
- NMIP4Config * self;
- NMIP4ConfigPrivate * priv;
- const NMDedupMultiHeadEntry *head_entry;
- NMDedupMultiIter iter;
- const NMPObject * plobj = NULL;
-
- nm_assert(ifindex > 0);
-
- /* Slaves have no IP configuration */
- if (nm_platform_link_get_master(platform, ifindex) > 0)
- return NULL;
-
- self = nm_ip4_config_new(multi_idx, ifindex);
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex);
- if (head_entry) {
- nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
- if (!_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip4_addresses_,
- ifindex,
- plobj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL))
- nm_assert_not_reached();
- }
- _notify_addresses(self);
- }
-
- head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex);
-
- /* Extract gateway from default route */
- nmp_cache_iter_for_each (&iter, head_entry, &plobj)
- _add_route(self, plobj, NULL, NULL);
-
- return self;
-}
-
-void
-nm_ip4_config_update_routes_metric(NMIP4Config *self, gint64 metric)
-{
- gs_free NMPlatformIP4Route *routes = NULL;
- gboolean need_update = FALSE;
- const NMPlatformIP4Route * r;
- NMDedupMultiIter iter;
- guint num = 0, i = 0;
-
- nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
- if (r->metric != metric)
- need_update = TRUE;
- num++;
- }
- if (!need_update)
- return;
-
- routes = g_new(NMPlatformIP4Route, num);
- nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
- routes[i] = *r;
- routes[i].metric = metric;
- i++;
- }
-
- g_object_freeze_notify(G_OBJECT(self));
- nm_ip4_config_reset_routes(self);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_route(self, &routes[i], NULL);
- g_object_thaw_notify(G_OBJECT(self));
-}
-
-void
-nm_ip4_config_add_dependent_routes(NMIP4Config *self,
- guint32 route_table,
- guint32 route_metric,
- gboolean is_vrf,
- GPtrArray ** out_ip4_dev_route_blacklist)
-{
- GPtrArray * ip4_dev_route_blacklist = NULL;
- const NMPlatformIP4Address *my_addr;
- const NMPlatformIP4Route * my_route;
- int ifindex;
- NMDedupMultiIter iter;
-
- g_return_if_fail(NM_IS_IP4_CONFIG(self));
-
- ifindex = nm_ip4_config_get_ifindex(self);
- g_return_if_fail(ifindex > 0);
-
- /* For IPv6 slaac, we explicitly add the device-routes (onlink) to NMIP6Config.
- * As we don't do that for IPv4 (and manual IPv6 addresses), add them explicitly. */
-
- nm_ip_config_iter_ip4_address_for_each (&iter, self, &my_addr) {
- nm_auto_nmpobj NMPObject *r = NULL;
- NMPlatformIP4Route * route;
- in_addr_t network;
-
- if (my_addr->plen == 0)
- continue;
-
- nm_assert(my_addr->plen <= 32);
-
- /* The destination network depends on the peer-address. */
- network = nm_utils_ip4_address_clear_host_address(my_addr->peer_address, my_addr->plen);
-
- if (my_addr->external)
- continue;
-
- if (nm_utils_ip4_address_is_zeronet(network)) {
- /* Kernel doesn't add device-routes for destinations that
- * start with 0.x.y.z. Skip them. */
- continue;
- }
-
- if (my_addr->plen == 32 && my_addr->address == my_addr->peer_address) {
- /* Kernel doesn't add device-routes for /32 addresses unless
- * they have a peer. */
- continue;
- }
-
- r = nmp_object_new(NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
- route = NMP_OBJECT_CAST_IP4_ROUTE(r);
-
- route->ifindex = ifindex;
- route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
- route->network = network;
- route->plen = my_addr->plen;
- route->pref_src = my_addr->address;
- route->table_coerced = nm_platform_route_table_coerce(route_table);
- route->metric = route_metric;
- route->scope_inv = nm_platform_route_scope_inv(NM_RT_SCOPE_LINK);
-
- nm_platform_ip_route_normalize(AF_INET, (NMPlatformIPRoute *) route);
-
- if (_lookup_route(self, r, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
- /* we already track this route. Don't add it again. */
- } else
- _add_route(self, r, NULL, NULL);
-
- if (out_ip4_dev_route_blacklist
- && (route_table != RT_TABLE_MAIN
- || route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE)) {
- nm_auto_nmpobj NMPObject *r_dev = NULL;
-
- r_dev = nmp_object_clone(r, FALSE);
- route = NMP_OBJECT_CAST_IP4_ROUTE(r_dev);
- route->table_coerced = nm_platform_route_table_coerce(RT_TABLE_MAIN);
- route->metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
-
- nm_platform_ip_route_normalize(AF_INET, (NMPlatformIPRoute *) route);
-
- if (_lookup_route(self, r_dev, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
- /* we track such a route explicitly. Don't blacklist it. */
- } else {
- if (!ip4_dev_route_blacklist)
- ip4_dev_route_blacklist =
- g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
-
- g_ptr_array_add(ip4_dev_route_blacklist, g_steal_pointer(&r_dev));
- }
- }
- }
-
-again:
- nm_ip_config_iter_ip4_route_for_each (&iter, self, &my_route) {
- NMPlatformIP4Route rt;
-
- if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(my_route) || my_route->gateway == 0
- || NM_IS_IP_CONFIG_SOURCE_RTPROT(my_route->rt_source)
- || nm_ip4_config_get_direct_route_for_host(
- self,
- my_route->gateway,
- nm_platform_route_table_uncoerce(my_route->table_coerced, TRUE)))
- continue;
-
- rt = *my_route;
- rt.network = my_route->gateway;
- rt.plen = 32;
- rt.gateway = 0;
- _add_route(self, NULL, &rt, NULL);
- /* adding the route might have invalidated the iteration. Start again. */
- goto again;
- }
-
- NM_SET_OUT(out_ip4_dev_route_blacklist, ip4_dev_route_blacklist);
-}
-
-gboolean
-nm_ip4_config_commit(const NMIP4Config * self,
- NMPlatform * platform,
- NMIPRouteTableSyncMode route_table_sync)
-{
- gs_unref_ptrarray GPtrArray *addresses = NULL;
- gs_unref_ptrarray GPtrArray *routes = NULL;
- gs_unref_ptrarray GPtrArray *routes_prune = NULL;
- int ifindex;
- gboolean success = TRUE;
-
- g_return_val_if_fail(NM_IS_IP4_CONFIG(self), FALSE);
-
- ifindex = nm_ip4_config_get_ifindex(self);
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- addresses =
- nm_dedup_multi_objs_to_ptr_array_head(nm_ip4_config_lookup_addresses(self), NULL, NULL);
-
- routes = nm_dedup_multi_objs_to_ptr_array_head(nm_ip4_config_lookup_routes(self), NULL, NULL);
-
- routes_prune =
- nm_platform_ip_route_get_prune_list(platform, AF_INET, ifindex, route_table_sync);
-
- nm_platform_ip4_address_sync(platform, ifindex, addresses);
-
- if (!nm_platform_ip_route_sync(platform, AF_INET, ifindex, routes, routes_prune, NULL))
- success = FALSE;
-
- return success;
-}
-
-void
-nm_ip4_config_merge_setting(NMIP4Config * self,
- NMSettingIPConfig * setting,
- NMSettingConnectionMdns mdns,
- NMSettingConnectionLlmnr llmnr,
- guint32 route_table,
- guint32 route_metric)
-{
- guint naddresses, nroutes, nnameservers, nsearches;
- int i, priority;
- const char *gateway_str;
- guint32 gateway_bin;
-
- if (!setting)
- return;
-
- g_return_if_fail(NM_IS_SETTING_IP4_CONFIG(setting));
-
- g_object_freeze_notify(G_OBJECT(self));
-
- naddresses = nm_setting_ip_config_get_num_addresses(setting);
- nroutes = nm_setting_ip_config_get_num_routes(setting);
- nnameservers = nm_setting_ip_config_get_num_dns(setting);
- nsearches = nm_setting_ip_config_get_num_dns_searches(setting);
-
- /* Gateway */
- if (!nm_setting_ip_config_get_never_default(setting)
- && (gateway_str = nm_setting_ip_config_get_gateway(setting))
- && inet_pton(AF_INET, gateway_str, &gateway_bin) == 1 && gateway_bin) {
- const NMPlatformIP4Route r = {
- .rt_source = NM_IP_CONFIG_SOURCE_USER,
- .gateway = gateway_bin,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
- };
-
- _add_route(self, NULL, &r, NULL);
- }
-
- /* Addresses */
- for (i = 0; i < naddresses; i++) {
- NMIPAddress * s_addr = nm_setting_ip_config_get_address(setting, i);
- GVariant * label;
- NMPlatformIP4Address address;
-
- 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);
- nm_assert(address.plen <= 32);
- address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
- address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
- address.addr_source = NM_IP_CONFIG_SOURCE_USER;
-
- label = nm_ip_address_get_attribute(s_addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
- if (label)
- g_strlcpy(address.label, g_variant_get_string(label, NULL), sizeof(address.label));
-
- _add_address(self, NULL, &address);
- }
-
- /* Routes */
- for (i = 0; i < nroutes; i++) {
- NMIPRoute * s_route = nm_setting_ip_config_get_route(setting, i);
- NMPlatformIP4Route route;
- gint64 m;
-
- if (nm_ip_route_get_family(s_route) != AF_INET) {
- nm_assert_not_reached();
- continue;
- }
-
- memset(&route, 0, sizeof(route));
- nm_ip_route_get_dest_binary(s_route, &route.network);
-
- route.plen = nm_ip_route_get_prefix(s_route);
- nm_assert(route.plen <= 32);
-
- nm_ip_route_get_next_hop_binary(s_route, &route.gateway);
- m = nm_ip_route_get_metric(s_route);
- if (m < 0)
- route.metric = route_metric;
- else
- route.metric = m;
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
-
- route.network = nm_utils_ip4_address_clear_host_address(route.network, route.plen);
-
- nm_utils_ip_route_attribute_to_platform(AF_INET,
- s_route,
- NM_PLATFORM_IP_ROUTE_CAST(&route),
- route_table);
- _add_route(self, NULL, &route, NULL);
- }
-
- /* DNS */
- if (nm_setting_ip_config_get_ignore_auto_dns(setting)) {
- nm_ip4_config_reset_nameservers(self);
- nm_ip4_config_reset_domains(self);
- nm_ip4_config_reset_searches(self);
- }
- for (i = 0; i < nnameservers; i++) {
- guint32 ip;
-
- if (inet_pton(AF_INET, nm_setting_ip_config_get_dns(setting, i), &ip) == 1)
- nm_ip4_config_add_nameserver(self, ip);
- }
- for (i = 0; i < nsearches; i++)
- nm_ip4_config_add_search(self, nm_setting_ip_config_get_dns_search(setting, i));
-
- i = 0;
- while ((i = nm_setting_ip_config_next_valid_dns_option(setting, i)) >= 0) {
- nm_ip4_config_add_dns_option(self, nm_setting_ip_config_get_dns_option(setting, i));
- i++;
- }
-
- priority = nm_setting_ip_config_get_dns_priority(setting);
- if (priority)
- nm_ip4_config_set_dns_priority(self, priority);
-
- nm_ip4_config_mdns_set(self, mdns);
- nm_ip4_config_llmnr_set(self, llmnr);
-
- nm_ip4_config_set_never_default(self, nm_setting_ip_config_get_never_default(setting));
-
- g_object_thaw_notify(G_OBJECT(self));
-}
-
-NMSetting *
-nm_ip4_config_create_setting(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate * priv;
- NMSettingIPConfig * s_ip4;
- guint nnameservers, nsearches, noptions;
- const char * method = NULL;
- int i;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *address;
- const NMPlatformIP4Route * route;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- s_ip4 = NM_SETTING_IP_CONFIG(nm_setting_ip4_config_new());
-
- if (!self) {
- g_object_set(s_ip4,
- NM_SETTING_IP_CONFIG_METHOD,
- NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
- NULL);
- return NM_SETTING(s_ip4);
- }
-
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nnameservers = nm_ip4_config_get_num_nameservers(self);
- nsearches = nm_ip4_config_get_num_searches(self);
- noptions = nm_ip4_config_get_num_dns_options(self);
-
- /* Addresses */
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address) {
- NMIPAddress *s_addr;
-
- /* Detect dynamic address */
- if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
- method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
- continue;
- }
-
- /* Static address found. */
- if (!method)
- method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
-
- s_addr = nm_ip_address_new_binary(AF_INET, &address->address, address->plen, NULL);
- if (*address->label)
- nm_ip_address_set_attribute(s_addr,
- NM_IP_ADDRESS_ATTRIBUTE_LABEL,
- g_variant_new_string(address->label));
-
- nm_setting_ip_config_add_address(s_ip4, s_addr);
- nm_ip_address_unref(s_addr);
- }
-
- /* Gateway */
- if (priv->best_default_route && nm_setting_ip_config_get_num_addresses(s_ip4) > 0) {
- g_object_set(
- s_ip4,
- NM_SETTING_IP_CONFIG_GATEWAY,
- _nm_utils_inet4_ntop(NMP_OBJECT_CAST_IP4_ROUTE(priv->best_default_route)->gateway,
- sbuf),
- NULL);
- }
-
- /* Use 'disabled' if the method wasn't previously set */
- if (!method)
- method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
-
- g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, method, NULL);
-
- /* Routes */
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
- NMIPRoute *s_route;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
- continue;
-
- /* Ignore routes provided by external sources */
- if (route->rt_source
- != nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER))
- continue;
-
- s_route = nm_ip_route_new_binary(AF_INET,
- &route->network,
- route->plen,
- &route->gateway,
- route->metric,
- NULL);
- nm_setting_ip_config_add_route(s_ip4, s_route);
- nm_ip_route_unref(s_route);
- }
-
- /* DNS */
- for (i = 0; i < nnameservers; i++) {
- guint32 nameserver = nm_ip4_config_get_nameserver(self, i);
-
- nm_setting_ip_config_add_dns(s_ip4, _nm_utils_inet4_ntop(nameserver, sbuf));
- }
- for (i = 0; i < nsearches; i++) {
- const char *search = nm_ip4_config_get_search(self, i);
-
- nm_setting_ip_config_add_dns_search(s_ip4, search);
- }
-
- for (i = 0; i < noptions; i++) {
- const char *option = nm_ip4_config_get_dns_option(self, i);
-
- nm_setting_ip_config_add_dns_option(s_ip4, option);
- }
-
- g_object_set(s_ip4,
- NM_SETTING_IP_CONFIG_DNS_PRIORITY,
- nm_ip4_config_get_dns_priority(self),
- NULL);
-
- return NM_SETTING(s_ip4);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_merge(NMIP4Config * dst,
- const NMIP4Config * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty)
-{
- NMIP4ConfigPrivate * dst_priv;
- const NMIP4ConfigPrivate * src_priv;
- guint32 i;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *address = NULL;
-
- g_return_if_fail(src != NULL);
- g_return_if_fail(dst != NULL);
-
- dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP4_CONFIG_GET_PRIVATE(src);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &address) {
- if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_EXTERNAL) && !address->external) {
- NMPlatformIP4Address a;
-
- a = *address;
- a.external = TRUE;
- _add_address(dst, NULL, &a);
- } else
- _add_address(dst, NMP_OBJECT_UP_CAST(address), NULL);
- }
-
- /* nameservers */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_nameservers(src); i++)
- nm_ip4_config_add_nameserver(dst, nm_ip4_config_get_nameserver(src, i));
- }
-
- /* routes */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
- const NMPlatformIP4Route *r_src;
-
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r_src) {
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) {
- if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES)
- && !NM_FLAGS_HAS(src_priv->config_flags,
- NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES))
- continue;
- if (default_route_metric_penalty) {
- NMPlatformIP4Route r = *r_src;
-
- r.metric =
- nm_utils_ip_route_metric_penalize(r.metric, default_route_metric_penalty);
- _add_route(dst, NULL, &r, NULL);
- continue;
- }
- }
- _add_route(dst, ipconf_iter.current->obj, NULL, NULL);
- }
- }
-
- /* domains */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_domains(src); i++)
- nm_ip4_config_add_domain(dst, nm_ip4_config_get_domain(src, i));
- }
-
- /* dns searches */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_searches(src); i++)
- nm_ip4_config_add_search(dst, nm_ip4_config_get_search(src, i));
- }
-
- /* dns options */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_dns_options(src); i++)
- nm_ip4_config_add_dns_option(dst, nm_ip4_config_get_dns_option(src, i));
- }
-
- /* MTU */
- if (src_priv->mtu_source > dst_priv->mtu_source
- || (src_priv->mtu_source == dst_priv->mtu_source
- && ((!dst_priv->mtu && src_priv->mtu)
- || (dst_priv->mtu && src_priv->mtu < dst_priv->mtu))))
- nm_ip4_config_set_mtu(dst, src_priv->mtu, src_priv->mtu_source);
-
- /* NIS */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_nis_servers(src); i++)
- nm_ip4_config_add_nis_server(dst, nm_ip4_config_get_nis_server(src, i));
-
- if (nm_ip4_config_get_nis_domain(src))
- nm_ip4_config_set_nis_domain(dst, nm_ip4_config_get_nis_domain(src));
- }
-
- /* WINS */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_wins(src); i++)
- nm_ip4_config_add_wins(dst, nm_ip4_config_get_wins(src, i));
- }
-
- /* metered flag */
- nm_ip4_config_set_metered(dst,
- nm_ip4_config_get_metered(dst) || nm_ip4_config_get_metered(src));
-
- /* never default */
- nm_ip4_config_set_never_default(dst,
- nm_ip4_config_get_never_default(dst)
- || nm_ip4_config_get_never_default(src));
-
- /* DNS priority */
- if (nm_ip4_config_get_dns_priority(src))
- nm_ip4_config_set_dns_priority(dst, nm_ip4_config_get_dns_priority(src));
-
- /* mdns */
- nm_ip4_config_mdns_set(dst, NM_MAX(nm_ip4_config_mdns_get(src), nm_ip4_config_mdns_get(dst)));
- /* LLMNR */
- nm_ip4_config_llmnr_set(dst,
- NM_MAX(nm_ip4_config_llmnr_get(src), nm_ip4_config_llmnr_get(dst)));
-
- g_object_thaw_notify(G_OBJECT(dst));
-}
-
-/*****************************************************************************/
-
-static int
-_nameservers_get_index(const NMIP4Config *self, guint32 ns)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->nameservers->len; i++) {
- guint32 n = g_array_index(priv->nameservers, guint32, i);
-
- if (ns == n)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_domains_get_index(const NMIP4Config *self, const char *domain)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->domains->len; i++) {
- const char *d = g_ptr_array_index(priv->domains, i);
-
- if (g_strcmp0(domain, d) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_searches_get_index(const NMIP4Config *self, const char *search)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->searches->len; i++) {
- const char *s = g_ptr_array_index(priv->searches, i);
-
- if (g_strcmp0(search, s) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_dns_options_get_index(const NMIP4Config *self, const char *option)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->dns_options->len; i++) {
- const char *s = g_ptr_array_index(priv->dns_options, i);
-
- if (g_strcmp0(option, s) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_nis_servers_get_index(const NMIP4Config *self, guint32 nis_server)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->nis->len; i++) {
- guint32 n = g_array_index(priv->nis, guint32, i);
-
- if (n == nis_server)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_wins_get_index(const NMIP4Config *self, guint32 wins_server)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->wins->len; i++) {
- guint32 n = g_array_index(priv->wins, guint32, i);
-
- if (n == wins_server)
- return (int) i;
- }
- return -1;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_ip4_config_subtract:
- * @dst: config from which to remove everything in @src
- * @src: config to remove from @dst
- * @default_route_metric_penalty: pretend that on source we applied
- * a route penalty on the default-route. It means, for default routes
- * we don't remove routes that match exactly, but those with a lower
- * metric (with the penalty removed).
- *
- * Removes everything in @src from @dst.
- */
-void
-nm_ip4_config_subtract(NMIP4Config * dst,
- const NMIP4Config *src,
- guint32 default_route_metric_penalty)
-{
- NMIP4ConfigPrivate * dst_priv;
- guint i;
- int idx;
- const NMPlatformIP4Address *a;
- const NMPlatformIP4Route * r;
- NMDedupMultiIter ipconf_iter;
- gboolean changed;
- gboolean changed_default_route;
-
- g_return_if_fail(src != NULL);
- g_return_if_fail(dst != NULL);
-
- dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- changed = FALSE;
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &a) {
- if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip4_addresses,
- NMP_OBJECT_UP_CAST(a),
- NULL))
- changed = TRUE;
- }
- if (changed)
- _notify_addresses(dst);
-
- /* nameservers */
- for (i = 0; i < nm_ip4_config_get_num_nameservers(src); i++) {
- idx = _nameservers_get_index(dst, nm_ip4_config_get_nameserver(src, i));
- if (idx >= 0)
- nm_ip4_config_del_nameserver(dst, idx);
- }
-
- /* routes */
- changed = FALSE;
- changed_default_route = FALSE;
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r) {
- const NMPObject * o_src = NMP_OBJECT_UP_CAST(r);
- NMPObject o_lookup_copy;
- const NMPObject * o_lookup;
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
- NMPlatformIP4Route *rr;
-
- /* the default route was penalized when merging it to the combined ip-config.
- * When subtracting the routes, we must re-do that process when comparing
- * the routes. */
- o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_src);
- rr = NMP_OBJECT_CAST_IP4_ROUTE(&o_lookup_copy);
- rr->metric =
- nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
- } else
- o_lookup = o_src;
-
- if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip4_routes,
- o_lookup,
- (gconstpointer *) &obj_old)) {
- if (dst_priv->best_default_route == obj_old) {
- nm_clear_nmp_object(&dst_priv->best_default_route);
- changed_default_route = TRUE;
- }
- changed = TRUE;
- }
- }
- if (changed_default_route) {
- nmp_object_ref_set(&dst_priv->best_default_route,
- _nm_ip4_config_best_default_route_find(dst));
- _notify(dst, PROP_GATEWAY);
- }
- if (changed)
- _notify_routes(dst);
-
- /* domains */
- for (i = 0; i < nm_ip4_config_get_num_domains(src); i++) {
- idx = _domains_get_index(dst, nm_ip4_config_get_domain(src, i));
- if (idx >= 0)
- nm_ip4_config_del_domain(dst, idx);
- }
-
- /* dns searches */
- for (i = 0; i < nm_ip4_config_get_num_searches(src); i++) {
- idx = _searches_get_index(dst, nm_ip4_config_get_search(src, i));
- if (idx >= 0)
- nm_ip4_config_del_search(dst, idx);
- }
-
- /* dns options */
- for (i = 0; i < nm_ip4_config_get_num_dns_options(src); i++) {
- idx = _dns_options_get_index(dst, nm_ip4_config_get_dns_option(src, i));
- if (idx >= 0)
- nm_ip4_config_del_dns_option(dst, idx);
- }
-
- /* MTU */
- if (nm_ip4_config_get_mtu(src) == nm_ip4_config_get_mtu(dst)
- && nm_ip4_config_get_mtu_source(src) == nm_ip4_config_get_mtu_source(dst))
- nm_ip4_config_set_mtu(dst, 0, NM_IP_CONFIG_SOURCE_UNKNOWN);
-
- /* NIS */
- for (i = 0; i < nm_ip4_config_get_num_nis_servers(src); i++) {
- idx = _nis_servers_get_index(dst, nm_ip4_config_get_nis_server(src, i));
- if (idx >= 0)
- nm_ip4_config_del_nis_server(dst, idx);
- }
-
- if (g_strcmp0(nm_ip4_config_get_nis_domain(src), nm_ip4_config_get_nis_domain(dst)) == 0)
- nm_ip4_config_set_nis_domain(dst, NULL);
-
- /* WINS */
- for (i = 0; i < nm_ip4_config_get_num_wins(src); i++) {
- idx = _wins_get_index(dst, nm_ip4_config_get_wins(src, i));
- if (idx >= 0)
- nm_ip4_config_del_wins(dst, idx);
- }
-
- /* DNS priority */
- if (nm_ip4_config_get_dns_priority(src) == nm_ip4_config_get_dns_priority(dst))
- nm_ip4_config_set_dns_priority(dst, 0);
-
- /* mdns */
- if (nm_ip4_config_mdns_get(src) == nm_ip4_config_mdns_get(dst))
- nm_ip4_config_mdns_set(dst, NM_SETTING_CONNECTION_MDNS_DEFAULT);
-
- /* LLMNR */
- if (nm_ip4_config_llmnr_get(src) == nm_ip4_config_llmnr_get(dst))
- nm_ip4_config_llmnr_set(dst, NM_SETTING_CONNECTION_LLMNR_DEFAULT);
-
- g_object_thaw_notify(G_OBJECT(dst));
-}
-
-static gboolean
-_nm_ip4_config_intersect_helper(NMIP4Config * dst,
- const NMIP4Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty,
- gboolean update_dst)
-{
- NMIP4ConfigPrivate * dst_priv;
- const NMIP4ConfigPrivate * src_priv;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *a;
- const NMPlatformIP4Route * r;
- const NMPObject * new_best_default_route;
- gboolean changed, result = FALSE;
-
- g_return_val_if_fail(src, FALSE);
- g_return_val_if_fail(dst, FALSE);
-
- dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP4_CONFIG_GET_PRIVATE(src);
-
- if (update_dst)
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- if (intersect_addresses) {
- changed = FALSE;
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, dst, &a) {
- if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
- &src_priv->idx_ip4_addresses,
- NMP_OBJECT_UP_CAST(a)))
- continue;
-
- if (!update_dst)
- return TRUE;
-
- if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
- nm_assert_not_reached();
- changed = TRUE;
- }
- if (changed) {
- _notify_addresses(dst);
- result = TRUE;
- }
- }
-
- /* ignore nameservers */
-
- /* routes */
- if (!intersect_routes)
- goto skip_routes;
-
- changed = FALSE;
- new_best_default_route = NULL;
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, dst, &r) {
- const NMPObject *o_dst = NMP_OBJECT_UP_CAST(r);
- const NMPObject *o_lookup;
- NMPObject o_lookup_copy;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
- NMPlatformIP4Route *rr;
-
- /* the default route was penalized when merging it to the combined ip-config.
- * When intersecting the routes, we must re-do that process when comparing
- * the routes. */
- o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_dst);
- rr = NMP_OBJECT_CAST_IP4_ROUTE(&o_lookup_copy);
- rr->metric =
- nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
- } else
- o_lookup = o_dst;
-
- if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
- &src_priv->idx_ip4_routes,
- o_lookup)) {
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, o_dst);
- continue;
- }
-
- if (!update_dst)
- return TRUE;
-
- if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
- nm_assert_not_reached();
- changed = TRUE;
- }
- if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route)) {
- nm_assert(changed);
- _notify(dst, PROP_GATEWAY);
- }
-
- if (changed) {
- _notify_routes(dst);
- result = TRUE;
- }
-
-skip_routes:
- /* ignore domains */
- /* ignore dns searches */
- /* ignore dns options */
- /* ignore NIS */
- /* ignore WINS */
- /* ignore mdns */
- /* ignore LLMNR */
-
- if (update_dst)
- g_object_thaw_notify(G_OBJECT(dst));
- return result;
-}
-
-/**
- * nm_ip4_config_intersect:
- * @dst: a configuration to be updated
- * @src: another configuration
- * @intersect_addresses: whether addresses should be intersected
- * @intersect_routes: whether routes should be intersected
- * @default_route_metric_penalty: the default route metric penalty
- *
- * Computes the intersection between @src and @dst and updates @dst in place
- * with the result.
- */
-void
-nm_ip4_config_intersect(NMIP4Config * dst,
- const NMIP4Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- _nm_ip4_config_intersect_helper(dst,
- src,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- TRUE);
-}
-
-/**
- * nm_ip4_config_intersect_alloc:
- * @a: a configuration
- * @b: another configuration
- * @intersect_addresses: whether addresses should be intersected
- * @intersect_routes: whether routes should be intersected
- * @default_route_metric_penalty: the default route metric penalty
- *
- * Computes the intersection between @a and @b and returns the result in a newly
- * allocated configuration. As a special case, if @a and @b are identical (with
- * respect to the only properties considered - addresses and routes) the
- * functions returns NULL so that one of existing configuration can be reused
- * without allocation.
- *
- * Returns: the intersection between @a and @b, or %NULL if the result is equal
- * to @a and @b.
- */
-NMIP4Config *
-nm_ip4_config_intersect_alloc(const NMIP4Config *a,
- const NMIP4Config *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- NMIP4Config *a_copy;
-
- if (_nm_ip4_config_intersect_helper((NMIP4Config *) a,
- b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- FALSE)) {
- a_copy = nm_ip4_config_clone(a);
- _nm_ip4_config_intersect_helper(a_copy,
- b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- TRUE);
- return a_copy;
- } else
- return NULL;
-}
-
-/**
- * nm_ip4_config_replace:
- * @dst: config to replace with @src content
- * @src: source config to copy
- * @relevant_changes: return whether there are changes to the
- * destination object that are relevant. This is equal to
- * nm_ip4_config_equal() showing any difference.
- *
- * Replaces everything in @dst with @src so that the two configurations
- * contain the same content -- with the exception of the dbus path.
- *
- * Returns: whether the @dst instance changed in any way (including minor changes,
- * that are not signaled by the output parameter @relevant_changes).
- */
-gboolean
-nm_ip4_config_replace(NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes)
-{
-#if NM_MORE_ASSERTS
- gboolean config_equal;
-#endif
- gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal;
- guint i, num;
- NMIP4ConfigPrivate * dst_priv;
- const NMIP4ConfigPrivate * src_priv;
- NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst;
- const NMDedupMultiHeadEntry *head_entry_src;
- const NMPObject * new_best_default_route;
-
- g_return_val_if_fail(src != NULL, FALSE);
- g_return_val_if_fail(dst != NULL, FALSE);
- g_return_val_if_fail(src != dst, FALSE);
-
-#if NM_MORE_ASSERTS
- config_equal = nm_ip4_config_equal(dst, src);
-#endif
-
- dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP4_CONFIG_GET_PRIVATE(src);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* ifindex */
- if (src_priv->ifindex != dst_priv->ifindex) {
- dst_priv->ifindex = src_priv->ifindex;
- has_minor_changes = TRUE;
- }
-
- /* addresses */
- head_entry_src = nm_ip4_config_lookup_addresses(src);
- nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
- nm_ip_config_iter_ip4_address_init(&ipconf_iter_dst, dst);
- are_equal = TRUE;
- while (TRUE) {
- gboolean has;
- const NMPlatformIP4Address *r_src = NULL;
- const NMPlatformIP4Address *r_dst = NULL;
-
- has = nm_platform_dedup_multi_iter_next_ip4_address(&ipconf_iter_src, &r_src);
- if (has != nm_platform_dedup_multi_iter_next_ip4_address(&ipconf_iter_dst, &r_dst)) {
- are_equal = FALSE;
- has_relevant_changes = TRUE;
- break;
- }
- if (!has)
- break;
-
- if (nm_platform_ip4_address_cmp(r_src, r_dst) != 0) {
- are_equal = FALSE;
- if (r_src->address != r_dst->address || r_src->plen != r_dst->plen
- || r_src->peer_address != r_dst->peer_address) {
- has_relevant_changes = TRUE;
- break;
- }
- }
- }
- if (!are_equal) {
- has_minor_changes = TRUE;
- nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip4_addresses);
- nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
- _nm_ip_config_add_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip4_addresses_,
- dst_priv->ifindex,
- ipconf_iter_src.current->obj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL);
- }
- nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
- &dst_priv->idx_ip4_addresses,
- FALSE);
- _notify_addresses(dst);
- }
-
- /* routes */
- head_entry_src = nm_ip4_config_lookup_routes(src);
- nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
- nm_ip_config_iter_ip4_route_init(&ipconf_iter_dst, dst);
- are_equal = TRUE;
- while (TRUE) {
- gboolean has;
- const NMPlatformIP4Route *r_src = NULL;
- const NMPlatformIP4Route *r_dst = NULL;
-
- has = nm_platform_dedup_multi_iter_next_ip4_route(&ipconf_iter_src, &r_src);
- if (has != nm_platform_dedup_multi_iter_next_ip4_route(&ipconf_iter_dst, &r_dst)) {
- are_equal = FALSE;
- has_relevant_changes = TRUE;
- break;
- }
- if (!has)
- break;
-
- if (nm_platform_ip4_route_cmp_full(r_src, r_dst) != 0) {
- are_equal = FALSE;
- if (r_src->plen != r_dst->plen
- || !nm_utils_ip4_address_same_prefix(r_src->network, r_dst->network, r_src->plen)
- || r_src->gateway != r_dst->gateway || r_src->metric != r_dst->metric) {
- has_relevant_changes = TRUE;
- break;
- }
- }
- }
- if (!are_equal) {
- has_minor_changes = TRUE;
- new_best_default_route = NULL;
- nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip4_routes);
- nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
- const NMPObject *o = ipconf_iter_src.current->obj;
- const NMPObject *obj_new;
-
- _nm_ip_config_add_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip4_routes_,
- dst_priv->ifindex,
- o,
- NULL,
- FALSE,
- TRUE,
- NULL,
- &obj_new);
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new);
- }
- nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
- &dst_priv->idx_ip4_routes,
- FALSE);
- if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route))
- _notify(dst, PROP_GATEWAY);
- _notify_routes(dst);
- }
-
- /* nameservers */
- num = nm_ip4_config_get_num_nameservers(src);
- are_equal = num == nm_ip4_config_get_num_nameservers(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (nm_ip4_config_get_nameserver(src, i) != nm_ip4_config_get_nameserver(dst, i)) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_nameservers(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_nameserver(dst, nm_ip4_config_get_nameserver(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* domains */
- num = nm_ip4_config_get_num_domains(src);
- are_equal = num == nm_ip4_config_get_num_domains(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip4_config_get_domain(src, i), nm_ip4_config_get_domain(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_domains(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_domain(dst, nm_ip4_config_get_domain(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* dns searches */
- num = nm_ip4_config_get_num_searches(src);
- are_equal = num == nm_ip4_config_get_num_searches(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip4_config_get_search(src, i), nm_ip4_config_get_search(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_searches(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_search(dst, nm_ip4_config_get_search(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* dns options */
- num = nm_ip4_config_get_num_dns_options(src);
- are_equal = num == nm_ip4_config_get_num_dns_options(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip4_config_get_dns_option(src, i),
- nm_ip4_config_get_dns_option(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_dns_options(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_dns_option(dst, nm_ip4_config_get_dns_option(src, i));
- has_relevant_changes = TRUE;
- }
-
- if (src_priv->mdns != dst_priv->mdns) {
- dst_priv->mdns = src_priv->mdns;
- has_relevant_changes = TRUE;
- }
-
- if (src_priv->llmnr != dst_priv->llmnr) {
- dst_priv->llmnr = src_priv->llmnr;
- has_relevant_changes = TRUE;
- }
-
- /* DNS priority */
- if (src_priv->dns_priority != dst_priv->dns_priority) {
- nm_ip4_config_set_dns_priority(dst, src_priv->dns_priority);
- has_minor_changes = TRUE;
- }
-
- /* nis */
- num = nm_ip4_config_get_num_nis_servers(src);
- are_equal = num == nm_ip4_config_get_num_nis_servers(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (nm_ip4_config_get_nis_server(src, i) != nm_ip4_config_get_nis_server(dst, i)) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_nis_servers(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_nis_server(dst, nm_ip4_config_get_nis_server(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* nis_domain */
- if (g_strcmp0(src_priv->nis_domain, dst_priv->nis_domain)) {
- nm_ip4_config_set_nis_domain(dst, src_priv->nis_domain);
- has_relevant_changes = TRUE;
- }
-
- /* wins */
- num = nm_ip4_config_get_num_wins(src);
- are_equal = num == nm_ip4_config_get_num_wins(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (nm_ip4_config_get_wins(src, i) != nm_ip4_config_get_wins(dst, i)) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_wins(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_wins(dst, nm_ip4_config_get_wins(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* mtu */
- if (src_priv->mtu != dst_priv->mtu || src_priv->mtu_source != dst_priv->mtu_source) {
- nm_ip4_config_set_mtu(dst, src_priv->mtu, src_priv->mtu_source);
- has_minor_changes = TRUE;
- }
-
- /* metered */
- if (src_priv->metered != dst_priv->metered) {
- dst_priv->metered = src_priv->metered;
- has_minor_changes = TRUE;
- }
-
- /* never default */
- if (src_priv->never_default != dst_priv->never_default) {
- dst_priv->never_default = src_priv->never_default;
- has_minor_changes = TRUE;
- }
-
-#if NM_MORE_ASSERTS
- /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes
- * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
- nm_assert(config_equal == !has_relevant_changes);
-#endif
-
- g_object_thaw_notify(G_OBJECT(dst));
-
- if (relevant_changes)
- *relevant_changes = has_relevant_changes;
-
- return has_relevant_changes || has_minor_changes;
-}
-
-void
-nm_ip_config_dump(const NMIPConfig *self, const char *detail, NMLogLevel level, NMLogDomain domain)
-{
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *addr4;
- const NMPlatformIP6Address *addr6;
- const NMPlatformIP4Route * route4;
- const NMPlatformIP6Route * route6;
- const NMIP4Config * ip4;
- const NMIP6Config * ip6;
- int addr_family = AF_UNSPEC;
- char addr_family_char = '?';
- const char * path;
- gconstpointer ptr;
- guint i;
-
- if (self) {
- addr_family = nm_ip_config_get_addr_family(self);
- addr_family_char = nm_utils_addr_family_to_char(addr_family);
- }
-
- nm_log(level, domain, NULL, NULL, "---- NMIP%cConfig %p (%s)", addr_family_char, self, detail);
-
- if (!self)
- return;
-
- path = nm_dbus_object_get_path(NM_DBUS_OBJECT(self));
- if (path)
- nm_log(level, domain, NULL, NULL, " path : %s", path);
-
- if (addr_family == AF_INET) {
- ip4 = NM_IP4_CONFIG(self);
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &addr4) {
- nm_log(level,
- domain,
- NULL,
- NULL,
- " address : %s",
- nm_platform_ip4_address_to_string(addr4, NULL, 0));
- }
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route4) {
- nm_log(level,
- domain,
- NULL,
- NULL,
- " route : %s",
- nm_platform_ip4_route_to_string(route4, NULL, 0));
- }
- } else {
- ip6 = NM_IP6_CONFIG(self);
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &addr6) {
- nm_log(level,
- domain,
- NULL,
- NULL,
- " address : %s",
- nm_platform_ip6_address_to_string(addr6, NULL, 0));
- }
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route6) {
- nm_log(level,
- domain,
- NULL,
- NULL,
- " route : %s",
- nm_platform_ip6_route_to_string(route6, NULL, 0));
- }
- }
-
- for (i = 0; i < nm_ip_config_get_num_nameservers(self); i++) {
- char buf[NM_UTILS_INET_ADDRSTRLEN];
-
- ptr = nm_ip_config_get_nameserver(self, i);
- nm_log(level,
- domain,
- NULL,
- NULL,
- " dns : %s",
- nm_utils_inet_ntop(addr_family, ptr, buf));
- }
-
- for (i = 0; i < nm_ip_config_get_num_domains(self); i++)
- nm_log(level, domain, NULL, NULL, " domain : %s", nm_ip_config_get_domain(self, i));
-
- for (i = 0; i < nm_ip_config_get_num_searches(self); i++)
- nm_log(level, domain, NULL, NULL, " search : %s", nm_ip_config_get_search(self, i));
-
- for (i = 0; i < nm_ip_config_get_num_dns_options(self); i++)
- nm_log(level, domain, NULL, NULL, "dns-option: %s", nm_ip_config_get_dns_option(self, i));
-
- nm_log(level, domain, NULL, NULL, " dns-prio : %d", nm_ip_config_get_dns_priority(self));
-
- if (addr_family == AF_INET) {
- ip4 = NM_IP4_CONFIG(self);
- nm_log(level,
- domain,
- NULL,
- NULL,
- " mtu : %" G_GUINT32_FORMAT " (source: %d)",
- nm_ip4_config_get_mtu(ip4),
- (int) nm_ip4_config_get_mtu_source(ip4));
- nm_log(level, domain, NULL, NULL, " metered : %d", (int) nm_ip4_config_get_metered(ip4));
- }
-}
-
-/*****************************************************************************/
-
-gconstpointer
-nm_ip_config_find_first_address(const NMIPConfig *self, NMPlatformMatchFlags match_flag)
-{
- NMDedupMultiIter iter;
- const NMPlatformIPAddress *address;
-
- g_return_val_if_fail(NM_IS_IP_CONFIG(self), NULL);
-
- nm_assert(!NM_FLAGS_ANY(
- match_flag,
- ~(NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)));
-
- nm_ip_config_iter_ip_address_for_each (&iter, self, &address) {
- if (nm_platform_ip_address_match(nm_ip_config_get_addr_family(self), address, match_flag))
- return address;
- }
-
- return NULL;
-}
-
-void
-nm_ip4_config_reset_addresses(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_addresses) > 0)
- _notify_addresses(self);
-}
-
-static void
-_add_address(NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip4_addresses_,
- priv->ifindex,
- obj_new,
- (const NMPlatformObject *) new,
- TRUE,
- FALSE,
- NULL,
- NULL))
- _notify_addresses(self);
-}
-
-/**
- * nm_ip4_config_add_address:
- * @self: the #NMIP4Config
- * @new: the new address to add to @self
- *
- * Adds the new address to @self. If an address with the same basic properties
- * (address, prefix) already exists in @self, it is overwritten with the
- * lifetime and preferred of @new. The source is also overwritten by the source
- * from @new if that source is higher priority.
- */
-void
-nm_ip4_config_add_address(NMIP4Config *self, const NMPlatformIP4Address *new)
-{
- g_return_if_fail(self);
- g_return_if_fail(new);
- g_return_if_fail(new->plen <= 32);
- g_return_if_fail(NM_IP4_CONFIG_GET_PRIVATE(self)->ifindex > 0);
-
- _add_address(self, NULL, new);
-}
-
-void
-_nmtst_ip4_config_del_address(NMIP4Config *self, guint i)
-{
- const NMPlatformIP4Address *a;
-
- a = _nmtst_ip4_config_get_address(self, i);
- if (!nm_ip4_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(a)))
- g_assert_not_reached();
-}
-
-guint
-nm_ip4_config_get_num_addresses(const NMIP4Config *self)
-{
- const NMDedupMultiHeadEntry *head_entry;
-
- head_entry = nm_ip4_config_lookup_addresses(self);
- return head_entry ? head_entry->len : 0;
-}
-
-const NMPlatformIP4Address *
-nm_ip4_config_get_first_address(const NMIP4Config *self)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP4Address *a = NULL;
-
- nm_ip_config_iter_ip4_address_for_each (&iter, self, &a)
- return a;
- return NULL;
-}
-
-const NMPlatformIP4Address *
-_nmtst_ip4_config_get_address(const NMIP4Config *self, guint i)
-{
- NMDedupMultiIter iter = {};
- const NMPlatformIP4Address *a = NULL;
- guint j;
-
- j = 0;
- nm_ip_config_iter_ip4_address_for_each (&iter, self, &a) {
- if (i == j)
- return a;
- j++;
- }
- g_return_val_if_reached(NULL);
-}
-
-gboolean
-nm_ip4_config_address_exists(const NMIP4Config *self, const NMPlatformIP4Address *needle)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- NMPObject obj_stack;
-
- nmp_object_stackinit_id_ip4_address(&obj_stack,
- priv->ifindex,
- needle->address,
- needle->plen,
- needle->peer_address);
- return !!nm_dedup_multi_index_lookup_obj(priv->multi_idx, &priv->idx_ip4_addresses, &obj_stack);
-}
-
-/*****************************************************************************/
-
-static const NMDedupMultiEntry *
-_lookup_route(const NMIP4Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type)
-{
- const NMIP4ConfigPrivate *priv;
-
- nm_assert(NM_IS_IP4_CONFIG(self));
- nm_assert(NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP4_ROUTE);
-
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return _nm_ip_config_lookup_ip_route(priv->multi_idx, &priv->idx_ip4_routes_, needle, cmp_type);
-}
-
-void
-nm_ip4_config_reset_routes(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_routes) > 0) {
- if (nm_clear_nmp_object(&priv->best_default_route))
- _notify(self, PROP_GATEWAY);
- _notify_routes(self);
- }
-}
-
-static void
-_add_route(NMIP4Config * self,
- const NMPObject *obj_new,
- const NMPlatformIP4Route *new,
- const NMPObject **out_obj_new)
-{
- NMIP4ConfigPrivate * priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
- const NMPObject * obj_new_2;
-
- nm_assert((!new) != (!obj_new));
- nm_assert(!new || _route_valid(new));
- nm_assert(!obj_new || _route_valid(NMP_OBJECT_CAST_IP4_ROUTE(obj_new)));
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip4_routes_,
- priv->ifindex,
- obj_new,
- (const NMPlatformObject *) new,
- TRUE,
- FALSE,
- &obj_old,
- &obj_new_2)) {
- gboolean changed_default_route = FALSE;
-
- if (priv->best_default_route == obj_old && obj_old != obj_new_2) {
- changed_default_route = TRUE;
- nm_clear_nmp_object(&priv->best_default_route);
- }
- NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
- if (_nm_ip_config_best_default_route_merge(&priv->best_default_route, obj_new_2))
- changed_default_route = TRUE;
-
- if (changed_default_route)
- _notify(self, PROP_GATEWAY);
- _notify_routes(self);
- } else
- NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
-}
-
-/**
- * nm_ip4_config_add_route:
- * @self: the #NMIP4Config
- * @new: the new route to add to @self
- * @out_obj_new: (allow-none) (out): the added route object. Must be unrefed
- * by caller.
- *
- * Adds the new route to @self. If a route with the same basic properties
- * (network, prefix) already exists in @self, it is overwritten including the
- * gateway and metric of @new. The source is also overwritten by the source
- * from @new if that source is higher priority.
- */
-void
-nm_ip4_config_add_route(NMIP4Config *self,
- const NMPlatformIP4Route *new,
- const NMPObject **out_obj_new)
-{
- g_return_if_fail(self);
- g_return_if_fail(new);
- g_return_if_fail(new->plen <= 32);
- g_return_if_fail(NM_IP4_CONFIG_GET_PRIVATE(self)->ifindex > 0);
-
- _add_route(self, NULL, new, out_obj_new);
-}
-
-void
-_nmtst_ip4_config_del_route(NMIP4Config *self, guint i)
-{
- const NMPlatformIP4Route *r;
-
- r = _nmtst_ip4_config_get_route(self, i);
- if (!nm_ip4_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(r)))
- g_assert_not_reached();
-}
-
-guint
-nm_ip4_config_get_num_routes(const NMIP4Config *self)
-{
- const NMDedupMultiHeadEntry *head_entry;
-
- head_entry = nm_ip4_config_lookup_routes(self);
- nm_assert(!head_entry || head_entry->len == c_list_length(&head_entry->lst_entries_head));
- return head_entry ? head_entry->len : 0;
-}
-
-const NMPlatformIP4Route *
-_nmtst_ip4_config_get_route(const NMIP4Config *self, guint i)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP4Route *r = NULL;
- guint j;
-
- j = 0;
- nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
- if (i == j)
- return r;
- j++;
- }
- g_return_val_if_reached(NULL);
-}
-
-const NMPlatformIP4Route *
-nm_ip4_config_get_direct_route_for_host(const NMIP4Config *self,
- in_addr_t host,
- guint32 route_table)
-{
- const NMPlatformIP4Route *best_route = NULL;
- const NMPlatformIP4Route *item;
- NMDedupMultiIter ipconf_iter;
-
- g_return_val_if_fail(host, NULL);
-
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &item) {
- if (item->gateway != 0)
- continue;
-
- if (best_route && best_route->plen > item->plen)
- continue;
-
- if (nm_platform_route_table_uncoerce(item->table_coerced, TRUE) != route_table)
- continue;
-
- if (nm_utils_ip4_address_clear_host_address(host, item->plen)
- != nm_utils_ip4_address_clear_host_address(item->network, item->plen))
- continue;
-
- if (best_route && best_route->metric <= item->metric)
- continue;
-
- best_route = item;
- }
- return best_route;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_nameservers(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->nameservers->len != 0) {
- g_array_set_size(priv->nameservers, 0);
- nm_gobject_notify_together(self, PROP_NAMESERVER_DATA, PROP_NAMESERVERS);
- }
-}
-
-void
-nm_ip4_config_add_nameserver(NMIP4Config *self, guint32 new)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(new != 0);
-
- for (i = 0; i < priv->nameservers->len; i++)
- if (new == g_array_index(priv->nameservers, guint32, i))
- return;
-
- g_array_append_val(priv->nameservers, new);
- nm_gobject_notify_together(self, PROP_NAMESERVER_DATA, PROP_NAMESERVERS);
-}
-
-void
-nm_ip4_config_del_nameserver(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->nameservers->len);
-
- g_array_remove_index(priv->nameservers, i);
- nm_gobject_notify_together(self, PROP_NAMESERVER_DATA, PROP_NAMESERVERS);
-}
-
-guint
-nm_ip4_config_get_num_nameservers(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->nameservers->len;
-}
-
-guint32
-nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_array_index(priv->nameservers, guint32, i);
-}
-
-const in_addr_t *
-_nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return &g_array_index(priv->nameservers, guint32, i);
-}
-
-/*****************************************************************************/
-
-gboolean
-_nm_ip_config_check_and_add_domain(GPtrArray *array, const char *domain)
-{
- char * copy = NULL;
- size_t len;
-
- g_return_val_if_fail(domain, FALSE);
- g_return_val_if_fail(domain[0] != '\0', FALSE);
-
- if (domain[0] == '.' || strstr(domain, ".."))
- return FALSE;
-
- len = strlen(domain);
- if (domain[len - 1] == '.')
- domain = copy = g_strndup(domain, len - 1);
-
- if (nm_strv_ptrarray_find_first(array, domain) >= 0) {
- g_free(copy);
- return FALSE;
- }
-
- g_ptr_array_add(array, copy ?: g_strdup(domain));
- return TRUE;
-}
-
-void
-nm_ip4_config_reset_domains(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->domains->len != 0) {
- g_ptr_array_set_size(priv->domains, 0);
- _notify(self, PROP_DOMAINS);
- }
-}
-
-void
-nm_ip4_config_add_domain(NMIP4Config *self, const char *domain)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_check_and_add_domain(priv->domains, domain))
- _notify(self, PROP_DOMAINS);
-}
-
-void
-nm_ip4_config_del_domain(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->domains->len);
-
- g_ptr_array_remove_index(priv->domains, i);
- _notify(self, PROP_DOMAINS);
-}
-
-guint
-nm_ip4_config_get_num_domains(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->domains->len;
-}
-
-const char *
-nm_ip4_config_get_domain(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->domains, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_searches(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->searches->len != 0) {
- g_ptr_array_set_size(priv->searches, 0);
- _notify(self, PROP_SEARCHES);
- }
-}
-
-void
-nm_ip4_config_add_search(NMIP4Config *self, const char *search)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_check_and_add_domain(priv->searches, search))
- _notify(self, PROP_SEARCHES);
-}
-
-void
-nm_ip4_config_del_search(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->searches->len);
-
- g_ptr_array_remove_index(priv->searches, i);
- _notify(self, PROP_SEARCHES);
-}
-
-guint
-nm_ip4_config_get_num_searches(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->searches->len;
-}
-
-const char *
-nm_ip4_config_get_search(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->searches, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_dns_options(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->dns_options->len != 0) {
- g_ptr_array_set_size(priv->dns_options, 0);
- _notify(self, PROP_DNS_OPTIONS);
- }
-}
-
-void
-nm_ip4_config_add_dns_option(NMIP4Config *self, const char *new)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(new != NULL);
- g_return_if_fail(new[0] != '\0');
-
- for (i = 0; i < priv->dns_options->len; i++)
- if (!g_strcmp0(g_ptr_array_index(priv->dns_options, i), new))
- return;
-
- g_ptr_array_add(priv->dns_options, g_strdup(new));
- _notify(self, PROP_DNS_OPTIONS);
-}
-
-void
-nm_ip4_config_del_dns_option(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->dns_options->len);
-
- g_ptr_array_remove_index(priv->dns_options, i);
- _notify(self, PROP_DNS_OPTIONS);
-}
-
-guint
-nm_ip4_config_get_num_dns_options(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->dns_options->len;
-}
-
-const char *
-nm_ip4_config_get_dns_option(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->dns_options, i);
-}
-
-/*****************************************************************************/
-
-NMSettingConnectionMdns
-nm_ip4_config_mdns_get(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->mdns;
-}
-
-void
-nm_ip4_config_mdns_set(NMIP4Config *self, NMSettingConnectionMdns mdns)
-{
- NM_IP4_CONFIG_GET_PRIVATE(self)->mdns = mdns;
-}
-
-NMSettingConnectionLlmnr
-nm_ip4_config_llmnr_get(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->llmnr;
-}
-
-void
-nm_ip4_config_llmnr_set(NMIP4Config *self, NMSettingConnectionLlmnr llmnr)
-{
- NM_IP4_CONFIG_GET_PRIVATE(self)->llmnr = llmnr;
-}
-
-/*****************************************************************************/
-
-NMIPConfigFlags
-nm_ip4_config_get_config_flags(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->config_flags;
-}
-
-void
-nm_ip4_config_set_config_flags(NMIP4Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (mask == 0) {
- /* for convenience, accept 0 mask to set any flags. */
- mask = flags;
- }
-
- nm_assert(!NM_FLAGS_ANY(flags, ~mask));
- priv->config_flags = (flags & mask) | (priv->config_flags & ~mask);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_set_dns_priority(NMIP4Config *self, int priority)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priority != priv->dns_priority) {
- priv->dns_priority = priority;
- _notify(self, PROP_DNS_PRIORITY);
- }
-}
-
-int
-nm_ip4_config_get_dns_priority(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->dns_priority;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_nis_servers(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_array_set_size(priv->nis, 0);
-}
-
-void
-nm_ip4_config_add_nis_server(NMIP4Config *self, guint32 nis)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- int i;
-
- for (i = 0; i < priv->nis->len; i++)
- if (nis == g_array_index(priv->nis, guint32, i))
- return;
-
- g_array_append_val(priv->nis, nis);
-}
-
-void
-nm_ip4_config_del_nis_server(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->nis->len);
-
- g_array_remove_index(priv->nis, i);
-}
-
-guint
-nm_ip4_config_get_num_nis_servers(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->nis->len;
-}
-
-guint32
-nm_ip4_config_get_nis_server(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_array_index(priv->nis, guint32, i);
-}
-
-void
-nm_ip4_config_set_nis_domain(NMIP4Config *self, const char *domain)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_free(priv->nis_domain);
- priv->nis_domain = g_strdup(domain);
-}
-
-const char *
-nm_ip4_config_get_nis_domain(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->nis_domain;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_wins(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->wins->len != 0) {
- g_array_set_size(priv->wins, 0);
- nm_gobject_notify_together(self, PROP_WINS_SERVER_DATA, PROP_WINS_SERVERS);
- }
-}
-
-void
-nm_ip4_config_add_wins(NMIP4Config *self, guint32 wins)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(wins != 0);
-
- for (i = 0; i < priv->wins->len; i++)
- if (wins == g_array_index(priv->wins, guint32, i))
- return;
-
- g_array_append_val(priv->wins, wins);
- nm_gobject_notify_together(self, PROP_WINS_SERVER_DATA, PROP_WINS_SERVERS);
-}
-
-void
-nm_ip4_config_del_wins(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->wins->len);
-
- g_array_remove_index(priv->wins, i);
- nm_gobject_notify_together(self, PROP_WINS_SERVER_DATA, PROP_WINS_SERVERS);
-}
-
-guint
-nm_ip4_config_get_num_wins(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->wins->len;
-}
-
-guint32
-nm_ip4_config_get_wins(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_array_index(priv->wins, guint32, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_set_mtu(NMIP4Config *self, guint32 mtu, NMIPConfigSource source)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (!mtu)
- source = NM_IP_CONFIG_SOURCE_UNKNOWN;
-
- priv->mtu = mtu;
- priv->mtu_source = source;
-}
-
-guint32
-nm_ip4_config_get_mtu(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->mtu;
-}
-
-NMIPConfigSource
-nm_ip4_config_get_mtu_source(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->mtu_source;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_set_metered(NMIP4Config *self, gboolean metered)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- priv->metered = metered;
-}
-
-gboolean
-nm_ip4_config_get_metered(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->metered;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_set_never_default(NMIP4Config *self, gboolean never_default)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- priv->never_default = never_default;
-}
-
-gboolean
-nm_ip4_config_get_never_default(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->never_default;
-}
-
-/*****************************************************************************/
-
-const NMPObject *
-nm_ip4_config_nmpobj_lookup(const NMIP4Config *self, const NMPObject *needle)
-{
- const NMIP4ConfigPrivate * priv;
- const NMDedupMultiIdxType *idx_type;
-
- g_return_val_if_fail(NM_IS_IP4_CONFIG(self), NULL);
-
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- switch (NMP_OBJECT_GET_TYPE(needle)) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- idx_type = &priv->idx_ip4_addresses;
- break;
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- idx_type = &priv->idx_ip4_routes;
- break;
- default:
- g_return_val_if_reached(NULL);
- }
-
- return nm_dedup_multi_entry_get_obj(
- nm_dedup_multi_index_lookup_obj(priv->multi_idx, idx_type, needle));
-}
-
-gboolean
-nm_ip4_config_nmpobj_remove(NMIP4Config *self, const NMPObject *needle)
-{
- NMIP4ConfigPrivate * priv;
- NMDedupMultiIdxType *idx_type;
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
- guint n;
-
- g_return_val_if_fail(NM_IS_IP4_CONFIG(self), FALSE);
-
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- switch (NMP_OBJECT_GET_TYPE(needle)) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- idx_type = &priv->idx_ip4_addresses;
- break;
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- idx_type = &priv->idx_ip4_routes;
- break;
- default:
- g_return_val_if_reached(FALSE);
- }
-
- n = nm_dedup_multi_index_remove_obj(priv->multi_idx,
- idx_type,
- needle,
- (gconstpointer *) &obj_old);
- if (n != 1) {
- nm_assert(n == 0);
- return FALSE;
- }
-
- nm_assert(NMP_OBJECT_GET_TYPE(obj_old) == NMP_OBJECT_GET_TYPE(needle));
-
- switch (NMP_OBJECT_GET_TYPE(obj_old)) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- _notify_addresses(self);
- break;
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- if (priv->best_default_route == obj_old) {
- if (nmp_object_ref_set(&priv->best_default_route,
- _nm_ip4_config_best_default_route_find(self)))
- _notify(self, PROP_GATEWAY);
- }
- _notify_routes(self);
- break;
- default:
- nm_assert_not_reached();
- }
- return TRUE;
-}
-
-/*****************************************************************************/
-
-static void
-hash_u32(GChecksum *sum, guint32 n)
-{
- g_checksum_update(sum, (const guint8 *) &n, sizeof(n));
-}
-
-void
-nm_ip4_config_hash(const NMIP4Config *self, GChecksum *sum, gboolean dns_only)
-{
- guint i;
- const char * s;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *address;
- const NMPlatformIP4Route * route;
- int val;
-
- g_return_if_fail(self);
- g_return_if_fail(sum);
-
- if (!dns_only) {
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address) {
- hash_u32(sum, address->address);
- hash_u32(sum, address->plen);
- hash_u32(sum, address->peer_address & _nm_utils_ip4_prefix_to_netmask(address->plen));
- }
-
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
- hash_u32(sum, route->network);
- hash_u32(sum, route->plen);
- hash_u32(sum, route->gateway);
- hash_u32(sum, route->metric);
- }
-
- for (i = 0; i < nm_ip4_config_get_num_nis_servers(self); i++)
- hash_u32(sum, nm_ip4_config_get_nis_server(self, i));
-
- s = nm_ip4_config_get_nis_domain(self);
- if (s)
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip4_config_get_num_nameservers(self); i++)
- hash_u32(sum, nm_ip4_config_get_nameserver(self, i));
-
- for (i = 0; i < nm_ip4_config_get_num_wins(self); i++)
- hash_u32(sum, nm_ip4_config_get_wins(self, i));
-
- for (i = 0; i < nm_ip4_config_get_num_domains(self); i++) {
- s = nm_ip4_config_get_domain(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip4_config_get_num_searches(self); i++) {
- s = nm_ip4_config_get_search(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip4_config_get_num_dns_options(self); i++) {
- s = nm_ip4_config_get_dns_option(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- val = nm_ip4_config_mdns_get(self);
- if (val != NM_SETTING_CONNECTION_MDNS_DEFAULT)
- g_checksum_update(sum, (const guint8 *) &val, sizeof(val));
-
- val = nm_ip4_config_llmnr_get(self);
- if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT)
- g_checksum_update(sum, (const guint8 *) &val, sizeof(val));
-
- /* FIXME(ip-config-checksum): the DNS priority should be considered relevant
- * and added into the checksum as well, but this can't be done right now
- * because in the DNS manager we rely on the fact that an empty
- * configuration (i.e. just created) has a zero checksum. This is needed to
- * avoid rewriting resolv.conf when there is no change.
- *
- * The DNS priority initial value depends on the connection type (VPN or
- * not), so it's a bit difficult to add it to checksum maintaining the
- * assumption of checksum(empty)=0
- */
-}
-
-/**
- * nm_ip4_config_equal:
- * @a: first config to compare
- * @b: second config to compare
- *
- * Compares two #NMIP4Configs for basic equality. This means that all
- * attributes must exist in the same order in both configs (addresses, routes,
- * domains, DNS servers, etc) but some attributes (address lifetimes, and address
- * and route sources) are ignored.
- *
- * Returns: %TRUE if the configurations are basically equal to each other,
- * %FALSE if not
- */
-gboolean
-nm_ip4_config_equal(const NMIP4Config *a, const NMIP4Config *b)
-{
- nm_auto_free_checksum GChecksum *a_checksum = g_checksum_new(G_CHECKSUM_SHA1);
- nm_auto_free_checksum GChecksum *b_checksum = g_checksum_new(G_CHECKSUM_SHA1);
- guint8 a_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
- guint8 b_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
-
- if (a)
- nm_ip4_config_hash(a, a_checksum, FALSE);
- if (b)
- nm_ip4_config_hash(b, b_checksum, FALSE);
-
- nm_utils_checksum_get_digest(a_checksum, a_data);
- nm_utils_checksum_get_digest(b_checksum, b_data);
- return !memcmp(a_data, b_data, sizeof(a_data));
-}
-
-/*****************************************************************************/
-
-static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
- NMIP4Config * self = NM_IP4_CONFIG(object);
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- char addr_str[NM_UTILS_INET_ADDRSTRLEN];
- GVariantBuilder builder_data;
- guint i;
-
- switch (prop_id) {
- case PROP_IFINDEX:
- g_value_set_int(value, priv->ifindex);
- break;
- case PROP_ADDRESS_DATA:
- case PROP_ADDRESSES:
- nm_assert(!!priv->address_data_variant == !!priv->addresses_variant);
-
- if (!priv->address_data_variant) {
- nm_utils_ip_addresses_to_dbus(AF_INET,
- nm_ip4_config_lookup_addresses(self),
- priv->best_default_route,
- NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
- &priv->address_data_variant,
- &priv->addresses_variant);
- g_variant_ref_sink(priv->address_data_variant);
- g_variant_ref_sink(priv->addresses_variant);
- }
-
- g_value_set_variant(value,
- prop_id == PROP_ADDRESS_DATA ? priv->address_data_variant
- : priv->addresses_variant);
- break;
- case PROP_ROUTE_DATA:
- case PROP_ROUTES:
- nm_assert(!!priv->route_data_variant == !!priv->routes_variant);
-
- if (!priv->route_data_variant) {
- nm_utils_ip_routes_to_dbus(AF_INET,
- nm_ip4_config_lookup_routes(self),
- &priv->route_data_variant,
- &priv->routes_variant);
- g_variant_ref_sink(priv->route_data_variant);
- g_variant_ref_sink(priv->routes_variant);
- }
-
- g_value_set_variant(value,
- prop_id == PROP_ROUTE_DATA ? priv->route_data_variant
- : priv->routes_variant);
- break;
- case PROP_GATEWAY:
- if (priv->best_default_route) {
- g_value_take_string(value,
- nm_utils_inet4_ntop_dup(
- NMP_OBJECT_CAST_IP4_ROUTE(priv->best_default_route)->gateway));
- } else
- g_value_set_string(value, NULL);
- break;
- case PROP_NAMESERVER_DATA:
- g_variant_builder_init(&builder_data, G_VARIANT_TYPE("aa{sv}"));
-
- for (i = 0; i < priv->nameservers->len; i++) {
- GVariantBuilder nested_builder;
-
- _nm_utils_inet4_ntop(g_array_index(priv->nameservers, in_addr_t, i), addr_str);
-
- g_variant_builder_init(&nested_builder, G_VARIANT_TYPE("a{sv}"));
- g_variant_builder_add(&nested_builder,
- "{sv}",
- "address",
- g_variant_new_string(addr_str));
- g_variant_builder_add(&builder_data, "a{sv}", &nested_builder);
- }
-
- g_value_take_variant(value, g_variant_builder_end(&builder_data));
- break;
- case PROP_NAMESERVERS:
- g_value_take_variant(
- value,
- nm_g_variant_new_au((const guint32 *) priv->nameservers->data, priv->nameservers->len));
- break;
- case PROP_DOMAINS:
- nm_utils_g_value_set_strv(value, priv->domains);
- break;
- case PROP_SEARCHES:
- nm_utils_g_value_set_strv(value, priv->searches);
- break;
- case PROP_DNS_OPTIONS:
- nm_utils_g_value_set_strv(value, priv->dns_options);
- break;
- case PROP_DNS_PRIORITY:
- g_value_set_int(value, priv->dns_priority);
- break;
- case PROP_WINS_SERVER_DATA:
- g_variant_builder_init(&builder_data, G_VARIANT_TYPE("as"));
- for (i = 0; i < priv->wins->len; i++) {
- g_variant_builder_add(
- &builder_data,
- "s",
- _nm_utils_inet4_ntop(g_array_index(priv->wins, in_addr_t, i), addr_str));
- }
- g_value_take_variant(value, g_variant_builder_end(&builder_data));
- break;
- case PROP_WINS_SERVERS:
- g_value_take_variant(
- value,
- nm_g_variant_new_au((const guint32 *) priv->wins->data, priv->wins->len));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-static void
-set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
- NMIP4Config * self = NM_IP4_CONFIG(object);
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- switch (prop_id) {
- case PROP_MULTI_IDX:
- /* construct-only */
- priv->multi_idx = g_value_get_pointer(value);
- if (!priv->multi_idx)
- g_return_if_reached();
- nm_dedup_multi_index_ref(priv->multi_idx);
- break;
- case PROP_IFINDEX:
- /* construct-only */
- priv->ifindex = g_value_get_int(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-/*****************************************************************************/
-
-static void
-nm_ip4_config_init(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_addresses,
- NMP_OBJECT_TYPE_IP4_ADDRESS);
- nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_routes,
- NMP_OBJECT_TYPE_IP4_ROUTE);
-
- priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
- priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
- priv->nameservers = g_array_new(FALSE, FALSE, sizeof(guint32));
- priv->domains = g_ptr_array_new_with_free_func(g_free);
- priv->searches = g_ptr_array_new_with_free_func(g_free);
- priv->dns_options = g_ptr_array_new_with_free_func(g_free);
- priv->nis = g_array_new(FALSE, TRUE, sizeof(guint32));
- priv->wins = g_array_new(FALSE, TRUE, sizeof(guint32));
-}
-
-NMIP4Config *
-nm_ip4_config_new(NMDedupMultiIndex *multi_idx, int ifindex)
-{
- g_return_val_if_fail(ifindex >= -1, NULL);
- return g_object_new(NM_TYPE_IP4_CONFIG,
- NM_IP4_CONFIG_MULTI_IDX,
- multi_idx,
- NM_IP4_CONFIG_IFINDEX,
- ifindex,
- NULL);
-}
-
-static void
-finalize(GObject *object)
-{
- NMIP4Config * self = NM_IP4_CONFIG(object);
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nm_clear_nmp_object(&priv->best_default_route);
-
- nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_addresses);
- nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_routes);
-
- nm_clear_g_variant(&priv->address_data_variant);
- nm_clear_g_variant(&priv->addresses_variant);
- nm_clear_g_variant(&priv->route_data_variant);
- nm_clear_g_variant(&priv->routes_variant);
-
- g_array_unref(priv->nameservers);
- g_ptr_array_unref(priv->domains);
- g_ptr_array_unref(priv->searches);
- g_ptr_array_unref(priv->dns_options);
- g_array_unref(priv->nis);
- g_free(priv->nis_domain);
- g_array_unref(priv->wins);
-
- G_OBJECT_CLASS(nm_ip4_config_parent_class)->finalize(object);
-
- nm_dedup_multi_index_unref(priv->multi_idx);
-}
-
-static const NMDBusInterfaceInfoExtended interface_info_ip4_config = {
- .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
- NM_DBUS_INTERFACE_IP4_CONFIG,
- .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses",
- "aau",
- NM_IP4_CONFIG_ADDRESSES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
- "aa{sv}",
- NM_IP4_CONFIG_ADDRESS_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP4_CONFIG_GATEWAY),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes", "aau", NM_IP4_CONFIG_ROUTES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData",
- "aa{sv}",
- NM_IP4_CONFIG_ROUTE_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NameserverData",
- "aa{sv}",
- NM_IP4_CONFIG_NAMESERVER_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers",
- "au",
- NM_IP4_CONFIG_NAMESERVERS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP4_CONFIG_DOMAINS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches",
- "as",
- NM_IP4_CONFIG_SEARCHES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions",
- "as",
- NM_IP4_CONFIG_DNS_OPTIONS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority",
- "i",
- NM_IP4_CONFIG_DNS_PRIORITY),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServerData",
- "as",
- NM_IP4_CONFIG_WINS_SERVER_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServers",
- "au",
- NM_IP4_CONFIG_WINS_SERVERS), ), ),
-};
-
-static void
-nm_ip4_config_class_init(NMIP4ConfigClass *klass)
-{
- GObjectClass * object_class = G_OBJECT_CLASS(klass);
- NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
- NMIPConfigClass * ip_config_class = NM_IP_CONFIG_CLASS(klass);
-
- ip_config_class->is_ipv4 = TRUE;
- ip_config_class->addr_family = AF_INET;
-
- dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/IP4Config");
- dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_ip4_config);
-
- object_class->get_property = get_property;
- object_class->set_property = set_property;
- object_class->finalize = finalize;
-
- obj_properties[PROP_MULTI_IDX] =
- g_param_spec_pointer(NM_IP4_CONFIG_MULTI_IDX,
- "",
- "",
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IFINDEX] =
- g_param_spec_int(NM_IP4_CONFIG_IFINDEX,
- "",
- "",
- -1,
- G_MAXINT,
- -1,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDRESS_DATA] =
- g_param_spec_variant(NM_IP4_CONFIG_ADDRESS_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDRESSES] =
- g_param_spec_variant(NM_IP4_CONFIG_ADDRESSES,
- "",
- "",
- G_VARIANT_TYPE("aau"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTE_DATA] =
- g_param_spec_variant(NM_IP4_CONFIG_ROUTE_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTES] = g_param_spec_variant(NM_IP4_CONFIG_ROUTES,
- "",
- "",
- G_VARIANT_TYPE("aau"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_GATEWAY] = g_param_spec_string(NM_IP4_CONFIG_GATEWAY,
- "",
- "",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_NAMESERVER_DATA] =
- g_param_spec_variant(NM_IP4_CONFIG_NAMESERVER_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_NAMESERVERS] =
- g_param_spec_variant(NM_IP4_CONFIG_NAMESERVERS,
- "",
- "",
- G_VARIANT_TYPE("au"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DOMAINS] = g_param_spec_boxed(NM_IP4_CONFIG_DOMAINS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_SEARCHES] = g_param_spec_boxed(NM_IP4_CONFIG_SEARCHES,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DNS_OPTIONS] =
- g_param_spec_boxed(NM_IP4_CONFIG_DNS_OPTIONS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DNS_PRIORITY] = g_param_spec_int(NM_IP4_CONFIG_DNS_PRIORITY,
- "",
- "",
- G_MININT32,
- G_MAXINT32,
- 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_WINS_SERVER_DATA] =
- g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVER_DATA,
- "",
- "",
- G_VARIANT_TYPE("as"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_WINS_SERVERS] =
- g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVERS,
- "",
- "",
- G_VARIANT_TYPE("au"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-}
diff --git a/src/core/nm-ip4-config.h b/src/core/nm-ip4-config.h
deleted file mode 100644
index 326b884def..0000000000
--- a/src/core/nm-ip4-config.h
+++ /dev/null
@@ -1,670 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2008 - 2013 Red Hat, Inc.
- */
-
-#ifndef __NETWORKMANAGER_IP4_CONFIG_H__
-#define __NETWORKMANAGER_IP4_CONFIG_H__
-
-#include "nm-setting-connection.h"
-
-#include "nm-setting-ip4-config.h"
-
-#include "libnm-glib-aux/nm-dedup-multi.h"
-#include "libnm-platform/nmp-object.h"
-#include "nm-ip-config.h"
-
-/*****************************************************************************/
-
-typedef enum _NMIPConfigFlags {
- NM_IP_CONFIG_FLAG_NONE = 0,
-
- /* if set, then the merge flag NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES gets
- * ignored during merge. */
- NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES = (1ull << 0),
-} NMIPConfigFlags;
-
-typedef struct {
- NMDedupMultiIdxType parent;
- NMPObjectType obj_type;
-} NMIPConfigDedupMultiIdxType;
-
-void nm_ip_config_dedup_multi_idx_type_init(NMIPConfigDedupMultiIdxType *idx_type,
- NMPObjectType obj_type);
-
-/*****************************************************************************/
-
-void nm_ip_config_iter_ip4_address_init(NMDedupMultiIter *iter, const NMIP4Config *self);
-void nm_ip_config_iter_ip4_route_init(NMDedupMultiIter *iter, const NMIP4Config *self);
-
-#define nm_ip_config_iter_ip4_address_for_each(iter, self, address) \
- for (nm_ip_config_iter_ip4_address_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip4_address((iter), (address));)
-
-#define nm_ip_config_iter_ip4_route_for_each(iter, self, route) \
- for (nm_ip_config_iter_ip4_route_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip4_route((iter), (route));)
-
-/*****************************************************************************/
-
-const NMPObject *_nm_ip_config_best_default_route_find_better(const NMPObject *obj_cur,
- const NMPObject *obj_cmp);
-gboolean _nm_ip_config_best_default_route_merge(const NMPObject **best_default_route,
- const NMPObject * new_candidate);
-
-/*****************************************************************************/
-
-gboolean _nm_ip_config_add_obj(NMDedupMultiIndex * multi_idx,
- NMIPConfigDedupMultiIdxType *idx_type,
- int ifindex,
- const NMPObject * obj_new,
- const NMPlatformObject * pl_new,
- gboolean merge,
- gboolean append_force,
- const NMPObject ** out_obj_old,
- const NMPObject ** out_obj_new);
-
-const NMDedupMultiEntry *_nm_ip_config_lookup_ip_route(const NMDedupMultiIndex * multi_idx,
- const NMIPConfigDedupMultiIdxType *idx_type,
- const NMPObject * needle,
- NMPlatformIPRouteCmpType cmp_type);
-
-/*****************************************************************************/
-
-#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type())
-#define NM_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IP4_CONFIG, NMIP4Config))
-#define NM_IP4_CONFIG_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass))
-#define NM_IS_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_IP4_CONFIG))
-#define NM_IS_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_IP4_CONFIG))
-#define NM_IP4_CONFIG_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass))
-
-typedef struct _NMIP4ConfigClass NMIP4ConfigClass;
-
-/* internal */
-#define NM_IP4_CONFIG_MULTI_IDX "multi-idx"
-#define NM_IP4_CONFIG_IFINDEX "ifindex"
-
-/* public*/
-#define NM_IP4_CONFIG_ADDRESS_DATA "address-data"
-#define NM_IP4_CONFIG_ROUTE_DATA "route-data"
-#define NM_IP4_CONFIG_GATEWAY "gateway"
-#define NM_IP4_CONFIG_NAMESERVER_DATA "nameserver-data"
-#define NM_IP4_CONFIG_DOMAINS "domains"
-#define NM_IP4_CONFIG_SEARCHES "searches"
-#define NM_IP4_CONFIG_DNS_OPTIONS "dns-options"
-#define NM_IP4_CONFIG_DNS_PRIORITY "dns-priority"
-#define NM_IP4_CONFIG_WINS_SERVER_DATA "wins-server-data"
-
-/* deprecated */
-#define NM_IP4_CONFIG_ADDRESSES "addresses"
-#define NM_IP4_CONFIG_ROUTES "routes"
-#define NM_IP4_CONFIG_NAMESERVERS "nameservers"
-#define NM_IP4_CONFIG_WINS_SERVERS "wins-servers"
-
-GType nm_ip4_config_get_type(void);
-
-NMIP4Config *nm_ip4_config_new(NMDedupMultiIndex *multi_idx, int ifindex);
-
-NMIP4Config *nm_ip4_config_clone(const NMIP4Config *self);
-int nm_ip4_config_get_ifindex(const NMIP4Config *self);
-
-NMDedupMultiIndex *nm_ip4_config_get_multi_idx(const NMIP4Config *self);
-
-NMIP4Config *nm_ip4_config_capture(NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex);
-
-void nm_ip4_config_add_dependent_routes(NMIP4Config *self,
- guint32 route_table,
- guint32 route_metric,
- gboolean is_vrf,
- GPtrArray ** out_ip4_dev_route_blacklist);
-
-gboolean nm_ip4_config_commit(const NMIP4Config * self,
- NMPlatform * platform,
- NMIPRouteTableSyncMode route_table_sync);
-
-void nm_ip4_config_merge_setting(NMIP4Config * self,
- NMSettingIPConfig * setting,
- NMSettingConnectionMdns mdns,
- NMSettingConnectionLlmnr llmnr,
- guint32 route_table,
- guint32 route_metric);
-NMSetting *nm_ip4_config_create_setting(const NMIP4Config *self);
-
-void nm_ip4_config_merge(NMIP4Config * dst,
- const NMIP4Config * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty);
-void nm_ip4_config_subtract(NMIP4Config * dst,
- const NMIP4Config *src,
- guint32 default_route_metric_penalty);
-void nm_ip4_config_intersect(NMIP4Config * dst,
- const NMIP4Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty);
-NMIP4Config *nm_ip4_config_intersect_alloc(const NMIP4Config *a,
- const NMIP4Config *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty);
-gboolean
-nm_ip4_config_replace(NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes);
-
-const NMPObject *nm_ip4_config_best_default_route_get(const NMIP4Config *self);
-const NMPObject *_nm_ip4_config_best_default_route_find(const NMIP4Config *self);
-
-in_addr_t nmtst_ip4_config_get_gateway(NMIP4Config *config);
-
-NMSettingConnectionMdns nm_ip4_config_mdns_get(const NMIP4Config *self);
-void nm_ip4_config_mdns_set(NMIP4Config *self, NMSettingConnectionMdns mdns);
-NMSettingConnectionLlmnr nm_ip4_config_llmnr_get(const NMIP4Config *self);
-void nm_ip4_config_llmnr_set(NMIP4Config *self, NMSettingConnectionLlmnr llmnr);
-
-void nm_ip4_config_set_config_flags(NMIP4Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask);
-NMIPConfigFlags nm_ip4_config_get_config_flags(const NMIP4Config *self);
-
-const NMDedupMultiHeadEntry *nm_ip4_config_lookup_addresses(const NMIP4Config *self);
-void nm_ip4_config_reset_addresses(NMIP4Config *self);
-void nm_ip4_config_add_address(NMIP4Config *self, const NMPlatformIP4Address *address);
-void _nmtst_ip4_config_del_address(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_addresses(const NMIP4Config *self);
-const NMPlatformIP4Address *nm_ip4_config_get_first_address(const NMIP4Config *self);
-const NMPlatformIP4Address *_nmtst_ip4_config_get_address(const NMIP4Config *self, guint i);
-gboolean nm_ip4_config_address_exists(const NMIP4Config *self, const NMPlatformIP4Address *address);
-
-const NMDedupMultiHeadEntry *nm_ip4_config_lookup_routes(const NMIP4Config *self);
-void nm_ip4_config_reset_routes(NMIP4Config *self);
-void nm_ip4_config_add_route(NMIP4Config * self,
- const NMPlatformIP4Route *route,
- const NMPObject ** out_obj_new);
-void _nmtst_ip4_config_del_route(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_routes(const NMIP4Config *self);
-const NMPlatformIP4Route * _nmtst_ip4_config_get_route(const NMIP4Config *self, guint i);
-
-const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host(const NMIP4Config *self,
- in_addr_t host,
- guint32 route_table);
-void nm_ip4_config_update_routes_metric(NMIP4Config *self, gint64 metric);
-
-void nm_ip4_config_reset_nameservers(NMIP4Config *self);
-void nm_ip4_config_add_nameserver(NMIP4Config *self, guint32 nameserver);
-
-static inline void
-_nm_ip4_config_add_nameserver(NMIP4Config *self, const guint32 *nameserver)
-{
- nm_ip4_config_add_nameserver(self, *nameserver);
-}
-
-void nm_ip4_config_del_nameserver(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_nameservers(const NMIP4Config *self);
-guint32 nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i);
-const in_addr_t *_nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_reset_domains(NMIP4Config *self);
-void nm_ip4_config_add_domain(NMIP4Config *self, const char *domain);
-void nm_ip4_config_del_domain(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_domains(const NMIP4Config *self);
-const char *nm_ip4_config_get_domain(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_reset_searches(NMIP4Config *self);
-void nm_ip4_config_add_search(NMIP4Config *self, const char *search);
-void nm_ip4_config_del_search(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_searches(const NMIP4Config *self);
-const char *nm_ip4_config_get_search(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_reset_dns_options(NMIP4Config *self);
-void nm_ip4_config_add_dns_option(NMIP4Config *self, const char *option);
-void nm_ip4_config_del_dns_option(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_dns_options(const NMIP4Config *self);
-const char *nm_ip4_config_get_dns_option(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_set_dns_priority(NMIP4Config *self, int priority);
-int nm_ip4_config_get_dns_priority(const NMIP4Config *self);
-
-void nm_ip4_config_reset_nis_servers(NMIP4Config *self);
-void nm_ip4_config_add_nis_server(NMIP4Config *self, guint32 nis);
-void nm_ip4_config_del_nis_server(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_nis_servers(const NMIP4Config *self);
-guint32 nm_ip4_config_get_nis_server(const NMIP4Config *self, guint i);
-void nm_ip4_config_set_nis_domain(NMIP4Config *self, const char *domain);
-const char *nm_ip4_config_get_nis_domain(const NMIP4Config *self);
-
-void nm_ip4_config_reset_wins(NMIP4Config *self);
-void nm_ip4_config_add_wins(NMIP4Config *self, guint32 wins);
-void nm_ip4_config_del_wins(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_wins(const NMIP4Config *self);
-guint32 nm_ip4_config_get_wins(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_set_mtu(NMIP4Config *self, guint32 mtu, NMIPConfigSource source);
-guint32 nm_ip4_config_get_mtu(const NMIP4Config *self);
-NMIPConfigSource nm_ip4_config_get_mtu_source(const NMIP4Config *self);
-
-void nm_ip4_config_set_metered(NMIP4Config *self, gboolean metered);
-gboolean nm_ip4_config_get_metered(const NMIP4Config *self);
-
-void nm_ip4_config_set_never_default(NMIP4Config *self, gboolean never_default);
-gboolean nm_ip4_config_get_never_default(const NMIP4Config *self);
-
-const NMPObject *nm_ip4_config_nmpobj_lookup(const NMIP4Config *self, const NMPObject *needle);
-gboolean nm_ip4_config_nmpobj_remove(NMIP4Config *self, const NMPObject *needle);
-
-void nm_ip4_config_hash(const NMIP4Config *self, GChecksum *sum, gboolean dns_only);
-gboolean nm_ip4_config_equal(const NMIP4Config *a, const NMIP4Config *b);
-
-gboolean _nm_ip_config_check_and_add_domain(GPtrArray *array, const char *domain);
-
-void
-nm_ip_config_dump(const NMIPConfig *self, const char *detail, NMLogLevel level, NMLogDomain domain);
-
-/*****************************************************************************/
-
-#include "nm-ip6-config.h"
-
-static inline gboolean
-NM_IS_IP_CONFIG_ADDR_FAMILY(gconstpointer config, int addr_family)
-{
- if (addr_family == AF_UNSPEC)
- return NM_IS_IP4_CONFIG(config) || NM_IS_IP6_CONFIG(config);
- if (addr_family == AF_INET)
- return NM_IS_IP4_CONFIG(config);
- if (addr_family == AF_INET6)
- return NM_IS_IP6_CONFIG(config);
- g_return_val_if_reached(FALSE);
-}
-
-#if _NM_CC_SUPPORT_GENERIC
-/* _NM_IS_IP_CONFIG() is a bit unusual. If _Generic() is supported,
- * it checks whether @config is either NM_IS_IP4_CONFIG() or NM_IS_IP6_CONFIG(),
- * depending on the pointer type of @config.
- *
- * For example, with _Generic() support, the following assertions would fail:
- * NMIP6Config *ptr = (NMIP6Config *) nm_ip4_config_new(...);
- * g_assert (_NM_IS_IP_CONFIG (ptr, ptr));
- * but the following would pass:
- * NMIP4Config *ptr = nm_ip4_config_new(...);
- * g_assert (_NM_IS_IP_CONFIG (ptr, ptr));
- */
-#define _NM_IS_IP_CONFIG(typeexpr, config) \
- ({ \
- const void *const _config = (config); \
- _Generic ((typeexpr), \
- const void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const void * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- void * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const NMIPConfig *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const NMIPConfig * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- NMIPConfig *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- NMIPConfig * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const NMIP4Config *const: (NM_IS_IP4_CONFIG (_config)), \
- const NMIP4Config * : (NM_IS_IP4_CONFIG (_config)), \
- NMIP4Config *const: (NM_IS_IP4_CONFIG (_config)), \
- NMIP4Config * : (NM_IS_IP4_CONFIG (_config)), \
- const NMIP6Config *const: (NM_IS_IP6_CONFIG (_config)), \
- const NMIP6Config * : (NM_IS_IP6_CONFIG (_config)), \
- NMIP6Config *const: (NM_IS_IP6_CONFIG (_config)), \
- NMIP6Config * : (NM_IS_IP6_CONFIG (_config))); \
- })
-#else
-#define _NM_IS_IP_CONFIG(typeexpr, config) NM_IS_IP_CONFIG(config)
-#endif
-
-#define NM_IP_CONFIG_CAST(config) \
- ({ \
- const void *const _configx = (config); \
- \
- nm_assert(!_configx || _NM_IS_IP_CONFIG((config), _configx)); \
- NM_CONSTCAST_FULL(NMIPConfig, (config), _configx, NMIP4Config, NMIP6Config); \
- })
-
-static inline gboolean
-nm_ip_config_is_ipv4(const NMIPConfig *config)
-{
- if (NM_IP_CONFIG_GET_CLASS(config)->is_ipv4) {
- nm_assert(NM_IS_IP4_CONFIG(config));
- return TRUE;
- }
- nm_assert(NM_IS_IP6_CONFIG(config));
- return FALSE;
-}
-
-static inline int
-nm_ip_config_get_addr_family(const NMIPConfig *config)
-{
- return nm_ip_config_is_ipv4(config) ? AF_INET : AF_INET6;
-}
-
-#define _NM_IP_CONFIG_DISPATCH(config, v4_func, v6_func, ...) \
- G_STMT_START \
- { \
- gconstpointer _config = (config); \
- \
- if (nm_ip_config_is_ipv4(_config)) { \
- return v4_func((NMIP4Config *) _config, ##__VA_ARGS__); \
- } else { \
- return v6_func((NMIP6Config *) _config, ##__VA_ARGS__); \
- } \
- } \
- G_STMT_END
-
-#define _NM_IP_CONFIG_DISPATCH_VOID(config, v4_func, v6_func, ...) \
- G_STMT_START \
- { \
- gconstpointer _config = (config); \
- \
- if (nm_ip_config_is_ipv4(_config)) { \
- v4_func((NMIP4Config *) _config, ##__VA_ARGS__); \
- } else { \
- v6_func((NMIP6Config *) _config, ##__VA_ARGS__); \
- } \
- } \
- G_STMT_END
-
-static inline int
-nm_ip_config_get_ifindex(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_ifindex, nm_ip6_config_get_ifindex);
-}
-
-static inline void
-nm_ip_config_hash(const NMIPConfig *self, GChecksum *sum, gboolean dns_only)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_hash, nm_ip6_config_hash, sum, dns_only);
-}
-
-static inline gconstpointer
-nm_ip_config_get_first_address(NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_first_address, nm_ip6_config_get_first_address);
-}
-
-static inline void
-nm_ip_config_iter_ip_address_init(NMDedupMultiIter *iter, const NMIPConfig *self)
-{
- if (nm_ip_config_is_ipv4(self))
- nm_ip_config_iter_ip4_address_init(iter, (const NMIP4Config *) self);
- else
- nm_ip_config_iter_ip6_address_init(iter, (const NMIP6Config *) self);
-}
-
-#define nm_ip_config_iter_ip_address_for_each(iter, self, address) \
- for (nm_ip_config_iter_ip_address_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip_address((iter), (address));)
-
-static inline void
-nm_ip_config_iter_ip_route_init(NMDedupMultiIter *iter, const NMIPConfig *self)
-{
- if (nm_ip_config_is_ipv4(self))
- nm_ip_config_iter_ip4_route_init(iter, (const NMIP4Config *) self);
- else
- nm_ip_config_iter_ip6_route_init(iter, (const NMIP6Config *) self);
-}
-
-#define nm_ip_config_iter_ip_route_for_each(iter, self, route) \
- for (nm_ip_config_iter_ip_route_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip_route((iter), (route));)
-
-static inline void
-nm_ip_config_add_address(NMIPConfig *self, const NMPlatformIPAddress *address)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_add_address,
- nm_ip6_config_add_address,
- (gconstpointer) address);
-}
-
-static inline void
-nm_ip_config_reset_addresses(NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_reset_addresses, nm_ip6_config_reset_addresses);
-}
-
-static inline void
-nm_ip_config_add_route(NMIPConfig *self,
- const NMPlatformIPRoute *new,
- const NMPObject **out_obj_new)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_add_route,
- nm_ip6_config_add_route,
- (gpointer) new,
- out_obj_new);
-}
-
-static inline void
-nm_ip_config_reset_routes(NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_reset_routes, nm_ip6_config_reset_routes);
-}
-
-static inline int
-nm_ip_config_get_dns_priority(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_dns_priority, nm_ip6_config_get_dns_priority);
-}
-
-static inline void
-nm_ip_config_set_dns_priority(NMIPConfig *self, int priority)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_set_dns_priority,
- nm_ip6_config_set_dns_priority,
- priority);
-}
-
-static inline void
-nm_ip_config_add_nameserver(NMIPConfig *self, const NMIPAddr *ns)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- _nm_ip4_config_add_nameserver,
- nm_ip6_config_add_nameserver,
- (gconstpointer) ns);
-}
-
-static inline void
-nm_ip_config_reset_nameservers(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_reset_nameservers,
- nm_ip6_config_reset_nameservers);
-}
-
-static inline guint
-nm_ip_config_get_num_nameservers(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self,
- nm_ip4_config_get_num_nameservers,
- nm_ip6_config_get_num_nameservers);
-}
-
-static inline gconstpointer
-nm_ip_config_get_nameserver(const NMIPConfig *self, guint i)
-{
- _NM_IP_CONFIG_DISPATCH(self, _nm_ip4_config_get_nameserver, nm_ip6_config_get_nameserver, i);
-}
-
-static inline guint
-nm_ip_config_get_num_domains(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_num_domains, nm_ip6_config_get_num_domains);
-}
-
-static inline const char *
-nm_ip_config_get_domain(const NMIPConfig *self, guint i)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_domain, nm_ip6_config_get_domain, i);
-}
-
-static inline void
-nm_ip_config_reset_searches(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_reset_searches, nm_ip6_config_reset_searches);
-}
-
-static inline void
-nm_ip_config_add_search(const NMIPConfig *self, const char *new)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_add_search, nm_ip6_config_add_search, new);
-}
-
-static inline guint
-nm_ip_config_get_num_searches(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_num_searches, nm_ip6_config_get_num_searches);
-}
-
-static inline const char *
-nm_ip_config_get_search(const NMIPConfig *self, guint i)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_search, nm_ip6_config_get_search, i);
-}
-
-static inline guint
-nm_ip_config_get_num_dns_options(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self,
- nm_ip4_config_get_num_dns_options,
- nm_ip6_config_get_num_dns_options);
-}
-
-static inline const char *
-nm_ip_config_get_dns_option(const NMIPConfig *self, guint i)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_dns_option, nm_ip6_config_get_dns_option, i);
-}
-
-static inline const NMPObject *
-nm_ip_config_best_default_route_get(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self,
- nm_ip4_config_best_default_route_get,
- nm_ip6_config_best_default_route_get);
-}
-
-static inline NMIPConfigFlags
-nm_ip_config_get_config_flags(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_config_flags, nm_ip6_config_get_config_flags);
-}
-
-static inline void
-nm_ip_config_set_config_flags(NMIPConfig *self, NMIPConfigFlags flags, NMIPConfigFlags mask)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_set_config_flags,
- nm_ip6_config_set_config_flags,
- flags,
- mask);
-}
-
-static inline gboolean
-nm_ip_config_get_never_default(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_never_default, nm_ip6_config_get_never_default);
-}
-
-static inline void
-nm_ip_config_set_never_default(NMIPConfig *self, gboolean never_default)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_set_never_default,
- nm_ip6_config_set_never_default,
- never_default);
-}
-
-#define _NM_IP_CONFIG_DISPATCH_SET_OP(_return, dst, src, v4_func, v6_func, ...) \
- G_STMT_START \
- { \
- gpointer _dst = (dst); \
- gconstpointer _src = (src); \
- \
- if (nm_ip_config_is_ipv4(_dst)) { \
- _return v4_func((NMIP4Config *) _dst, (const NMIP4Config *) _src, ##__VA_ARGS__); \
- } else { \
- _return v6_func((NMIP6Config *) _dst, (const NMIP6Config *) _src, ##__VA_ARGS__); \
- } \
- } \
- G_STMT_END
-
-static inline void
-nm_ip_config_intersect(NMIPConfig * dst,
- const NMIPConfig *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- _NM_IP_CONFIG_DISPATCH_SET_OP(,
- dst,
- src,
- nm_ip4_config_intersect,
- nm_ip6_config_intersect,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty);
-}
-
-static inline void
-nm_ip_config_subtract(NMIPConfig *dst, const NMIPConfig *src, guint32 default_route_metric_penalty)
-{
- _NM_IP_CONFIG_DISPATCH_SET_OP(,
- dst,
- src,
- nm_ip4_config_subtract,
- nm_ip6_config_subtract,
- default_route_metric_penalty);
-}
-
-static inline void
-nm_ip_config_merge(NMIPConfig * dst,
- const NMIPConfig * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty)
-{
- _NM_IP_CONFIG_DISPATCH_SET_OP(,
- dst,
- src,
- nm_ip4_config_merge,
- nm_ip6_config_merge,
- merge_flags,
- default_route_metric_penalty);
-}
-
-static inline gboolean
-nm_ip_config_replace(NMIPConfig *dst, const NMIPConfig *src, gboolean *relevant_changes)
-{
- _NM_IP_CONFIG_DISPATCH_SET_OP(
- return, dst, src, nm_ip4_config_replace, nm_ip6_config_replace, relevant_changes);
-}
-
-static inline NMIPConfig *
-nm_ip_config_intersect_alloc(const NMIPConfig *a,
- const NMIPConfig *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- if (nm_ip_config_is_ipv4(a)) {
- nm_assert(NM_IS_IP4_CONFIG(a));
- nm_assert(NM_IS_IP4_CONFIG(b));
- return (NMIPConfig *) nm_ip4_config_intersect_alloc((const NMIP4Config *) a,
- (const NMIP4Config *) b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty);
- } else {
- nm_assert(NM_IS_IP6_CONFIG(a));
- nm_assert(NM_IS_IP6_CONFIG(b));
- return (NMIPConfig *) nm_ip6_config_intersect_alloc((const NMIP6Config *) a,
- (const NMIP6Config *) b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty);
- }
-}
-
-gconstpointer nm_ip_config_find_first_address(const NMIPConfig * self,
- NMPlatformMatchFlags match_flag);
-
-#endif /* __NETWORKMANAGER_IP4_CONFIG_H__ */
diff --git a/src/core/nm-ip6-config.c b/src/core/nm-ip6-config.c
deleted file mode 100644
index 5ec68bd28c..0000000000
--- a/src/core/nm-ip6-config.c
+++ /dev/null
@@ -1,2675 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2005 - 2017 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "nm-ip6-config.h"
-
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <linux/rtnetlink.h>
-#include <linux/if.h>
-
-#include "libnm-glib-aux/nm-dedup-multi.h"
-
-#include "nm-utils.h"
-#include "libnm-platform/nmp-object.h"
-#include "libnm-platform/nm-platform.h"
-#include "libnm-platform/nm-platform-utils.h"
-#include "libnm-core-intern/nm-core-internal.h"
-#include "NetworkManagerUtils.h"
-#include "nm-ip4-config.h"
-#include "ndisc/nm-ndisc.h"
-#include "nm-dbus-object.h"
-
-/*****************************************************************************/
-
-static gboolean
-_route_valid(const NMPlatformIP6Route *r)
-{
- struct in6_addr n;
-
- return r && r->plen <= 128
- && (memcmp(&r->network,
- nm_utils_ip6_address_clear_host_address(&n, &r->network, r->plen),
- sizeof(n))
- == 0);
-}
-
-/*****************************************************************************/
-
-typedef struct {
- int ifindex;
- int dns_priority;
- NMSettingIP6ConfigPrivacy privacy;
- GArray * nameservers;
- GPtrArray * domains;
- GPtrArray * searches;
- GPtrArray * dns_options;
- GVariant * address_data_variant;
- GVariant * addresses_variant;
- GVariant * route_data_variant;
- GVariant * routes_variant;
- NMDedupMultiIndex * multi_idx;
- const NMPObject * best_default_route;
- union {
- NMIPConfigDedupMultiIdxType idx_ip6_addresses_;
- NMDedupMultiIdxType idx_ip6_addresses;
- };
- union {
- NMIPConfigDedupMultiIdxType idx_ip6_routes_;
- NMDedupMultiIdxType idx_ip6_routes;
- };
- NMIPConfigFlags config_flags;
- bool never_default : 1;
-} NMIP6ConfigPrivate;
-
-struct _NMIP6Config {
- NMIPConfig parent;
- NMIP6ConfigPrivate _priv;
-};
-
-struct _NMIP6ConfigClass {
- NMIPConfigClass parent;
-};
-
-G_DEFINE_TYPE(NMIP6Config, nm_ip6_config, NM_TYPE_IP_CONFIG)
-
-#define NM_IP6_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIP6Config, NM_IS_IP6_CONFIG)
-
-NM_GOBJECT_PROPERTIES_DEFINE(NMIP6Config,
- PROP_MULTI_IDX,
- PROP_IFINDEX,
- PROP_ADDRESS_DATA,
- PROP_ADDRESSES,
- PROP_ROUTE_DATA,
- PROP_ROUTES,
- PROP_GATEWAY,
- PROP_NAMESERVERS,
- PROP_DOMAINS,
- PROP_SEARCHES,
- PROP_DNS_OPTIONS,
- PROP_DNS_PRIORITY, );
-
-/*****************************************************************************/
-
-static void
-_add_address(NMIP6Config *self, const NMPObject *obj_new, const NMPlatformIP6Address *new);
-static void _add_route(NMIP6Config * self,
- const NMPObject *obj_new,
- const NMPlatformIP6Route *new,
- const NMPObject **out_obj_new);
-static const NMDedupMultiEntry *
-_lookup_route(const NMIP6Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type);
-
-/*****************************************************************************/
-
-int
-nm_ip6_config_get_ifindex(const NMIP6Config *self)
-{
- return NM_IP6_CONFIG_GET_PRIVATE(self)->ifindex;
-}
-
-NMDedupMultiIndex *
-nm_ip6_config_get_multi_idx(const NMIP6Config *self)
-{
- return NM_IP6_CONFIG_GET_PRIVATE(self)->multi_idx;
-}
-
-void
-nm_ip6_config_set_privacy(NMIP6Config *self, NMSettingIP6ConfigPrivacy privacy)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- priv->privacy = privacy;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_set_never_default(NMIP6Config *self, gboolean never_default)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- priv->never_default = never_default;
-}
-
-gboolean
-nm_ip6_config_get_never_default(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->never_default;
-}
-
-/*****************************************************************************/
-
-const NMDedupMultiHeadEntry *
-nm_ip6_config_lookup_addresses(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip6_addresses, NULL);
-}
-
-void
-nm_ip_config_iter_ip6_address_init(NMDedupMultiIter *ipconf_iter, const NMIP6Config *self)
-{
- nm_assert(NM_IS_IP6_CONFIG(self));
-
- nm_dedup_multi_iter_init(ipconf_iter, nm_ip6_config_lookup_addresses(self));
-}
-
-/*****************************************************************************/
-
-const NMDedupMultiHeadEntry *
-nm_ip6_config_lookup_routes(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip6_routes, NULL);
-}
-
-void
-nm_ip_config_iter_ip6_route_init(NMDedupMultiIter *ipconf_iter, const NMIP6Config *self)
-{
- nm_assert(NM_IS_IP6_CONFIG(self));
-
- nm_dedup_multi_iter_init(ipconf_iter, nm_ip6_config_lookup_routes(self));
-}
-
-/*****************************************************************************/
-
-const NMPObject *
-nm_ip6_config_best_default_route_get(const NMIP6Config *self)
-{
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), NULL);
-
- return NM_IP6_CONFIG_GET_PRIVATE(self)->best_default_route;
-}
-
-const NMPObject *
-_nm_ip6_config_best_default_route_find(const NMIP6Config *self)
-{
- NMDedupMultiIter ipconf_iter;
- const NMPObject *new_best_default_route = NULL;
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, NULL) {
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route,
- ipconf_iter.current->obj);
- }
- return new_best_default_route;
-}
-
-/*****************************************************************************/
-
-static void
-_notify_addresses(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nm_clear_g_variant(&priv->address_data_variant);
- nm_clear_g_variant(&priv->addresses_variant);
- nm_gobject_notify_together(self, PROP_ADDRESS_DATA, PROP_ADDRESSES);
-}
-
-static void
-_notify_routes(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nm_assert(priv->best_default_route == _nm_ip6_config_best_default_route_find(self));
- nm_clear_g_variant(&priv->route_data_variant);
- nm_clear_g_variant(&priv->routes_variant);
- nm_gobject_notify_together(self, PROP_ROUTE_DATA, PROP_ROUTES);
-}
-
-/*****************************************************************************/
-
-static int
-sort_captured_addresses(const CList *lst_a, const CList *lst_b, gconstpointer user_data)
-{
- return nm_platform_ip6_address_pretty_sort_cmp(
- NMP_OBJECT_CAST_IP6_ADDRESS(c_list_entry(lst_a, NMDedupMultiEntry, lst_entries)->obj),
- NMP_OBJECT_CAST_IP6_ADDRESS(c_list_entry(lst_b, NMDedupMultiEntry, lst_entries)->obj),
- (((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT(user_data))
- == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
-}
-
-gboolean
-_nmtst_ip6_config_addresses_sort(NMIP6Config *self)
-{
- NMIP6ConfigPrivate * priv;
- const NMDedupMultiHeadEntry *head_entry;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), FALSE);
-
- head_entry = nm_ip6_config_lookup_addresses(self);
- if (head_entry && head_entry->len > 1) {
- gboolean changed;
- gs_free gconstpointer *addresses_old = NULL;
- guint naddr, j;
- NMDedupMultiIter iter;
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- addresses_old = nm_dedup_multi_objs_to_array_head(head_entry, NULL, NULL, &naddr);
- nm_assert(addresses_old);
- nm_assert(naddr > 0 && naddr == head_entry->len);
-
- nm_dedup_multi_head_entry_sort(head_entry,
- sort_captured_addresses,
- GINT_TO_POINTER(priv->privacy));
-
- changed = FALSE;
- j = 0;
- nm_dedup_multi_iter_for_each (&iter, head_entry) {
- nm_assert(j < naddr);
- if (iter.current->obj != addresses_old[j++])
- changed = TRUE;
- }
- nm_assert(j == naddr);
-
- if (changed) {
- _notify_addresses(self);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-NMIP6Config *
-nm_ip6_config_clone(const NMIP6Config *self)
-{
- NMIP6Config *copy;
-
- copy = nm_ip6_config_new(nm_ip6_config_get_multi_idx(self), -1);
- nm_ip6_config_replace(copy, self, NULL);
-
- return copy;
-}
-
-NMIP6Config *
-nm_ip6_config_capture(NMDedupMultiIndex * multi_idx,
- NMPlatform * platform,
- int ifindex,
- NMSettingIP6ConfigPrivacy use_temporary)
-{
- NMIP6Config * self;
- NMIP6ConfigPrivate * priv;
- const NMDedupMultiHeadEntry *head_entry;
- NMDedupMultiIter iter;
- const NMPObject * plobj = NULL;
-
- nm_assert(ifindex > 0);
-
- /* Slaves have no IP configuration */
- if (nm_platform_link_get_master(platform, ifindex) > 0)
- return NULL;
-
- self = nm_ip6_config_new(multi_idx, ifindex);
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex);
- if (head_entry) {
- nmp_cache_iter_for_each_reverse (&iter, head_entry, &plobj) {
- if (!_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_addresses_,
- ifindex,
- plobj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL))
- nm_assert_not_reached();
- }
- _notify_addresses(self);
- }
-
- head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex);
-
- nmp_cache_iter_for_each (&iter, head_entry, &plobj)
- _add_route(self, plobj, NULL, NULL);
-
- return self;
-}
-
-void
-nm_ip6_config_update_routes_metric(NMIP6Config *self, gint64 metric)
-{
- gs_free NMPlatformIP6Route *routes = NULL;
- gboolean need_update = FALSE;
- const NMPlatformIP6Route * r;
- NMDedupMultiIter iter;
- guint num = 0, i = 0;
-
- nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) {
- if (r->metric != metric)
- need_update = TRUE;
- num++;
- }
- if (!need_update)
- return;
-
- routes = g_new(NMPlatformIP6Route, num);
- nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) {
- routes[i] = *r;
- routes[i].metric = metric;
- i++;
- }
-
- g_object_freeze_notify(G_OBJECT(self));
- nm_ip6_config_reset_routes(self);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_route(self, &routes[i], NULL);
- g_object_thaw_notify(G_OBJECT(self));
-}
-
-void
-nm_ip6_config_add_dependent_routes(NMIP6Config *self,
- guint32 route_table,
- guint32 route_metric,
- gboolean is_vrf)
-{
- const NMPlatformIP6Address *my_addr;
- const NMPlatformIP6Route * my_route;
- int ifindex;
- NMDedupMultiIter iter;
-
- g_return_if_fail(NM_IS_IP6_CONFIG(self));
-
- ifindex = nm_ip6_config_get_ifindex(self);
- g_return_if_fail(ifindex > 0);
-
- /* For IPv6 addresses received via SLAAC/autoconf, we explicitly add the
- * device-routes (onlink) to NMIP6Config.
- *
- * For manually added IPv6 routes, add the device routes explicitly. */
-
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &my_addr) {
- NMPlatformIP6Route *route;
- gboolean has_peer;
- int routes_n, routes_i;
-
- if (my_addr->external)
- continue;
-
- if (NM_FLAGS_HAS(my_addr->n_ifa_flags, IFA_F_NOPREFIXROUTE))
- continue;
- if (my_addr->plen == 0)
- continue;
-
- has_peer = !IN6_IS_ADDR_UNSPECIFIED(&my_addr->peer_address);
-
- /* If we have an IPv6 peer, we add two /128 routes
- * (unless, both addresses are identical). */
- routes_n =
- (has_peer && !IN6_ARE_ADDR_EQUAL(&my_addr->address, &my_addr->peer_address)) ? 2 : 1;
-
- for (routes_i = 0; routes_i < routes_n; routes_i++) {
- nm_auto_nmpobj NMPObject *r = NULL;
-
- r = nmp_object_new(NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
- route = NMP_OBJECT_CAST_IP6_ROUTE(r);
-
- route->ifindex = ifindex;
- route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
- route->table_coerced = nm_platform_route_table_coerce(route_table);
- route->metric = route_metric;
-
- if (has_peer) {
- if (routes_i == 0)
- route->network = my_addr->address;
- else
- route->network = my_addr->peer_address;
- route->plen = 128;
- } else {
- nm_utils_ip6_address_clear_host_address(&route->network,
- &my_addr->address,
- my_addr->plen);
- route->plen = my_addr->plen;
- }
-
- nm_platform_ip_route_normalize(AF_INET6, (NMPlatformIPRoute *) route);
-
- if (_lookup_route(self, r, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
- /* we already track this route. Don't add it again. */
- } else
- _add_route(self, r, NULL, NULL);
- }
- }
-
-again:
- nm_ip_config_iter_ip6_route_for_each (&iter, self, &my_route) {
- NMPlatformIP6Route rt;
-
- if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(my_route)
- || IN6_IS_ADDR_UNSPECIFIED(&my_route->gateway)
- || NM_IS_IP_CONFIG_SOURCE_RTPROT(my_route->rt_source)
- || nm_ip6_config_get_direct_route_for_host(
- self,
- &my_route->gateway,
- nm_platform_route_table_uncoerce(my_route->table_coerced, TRUE)))
- continue;
-
- rt = *my_route;
- rt.network = my_route->gateway;
- rt.plen = 128;
- rt.gateway = in6addr_any;
- _add_route(self, NULL, &rt, NULL);
- /* adding the route might have invalidated the iteration. Start again. */
- goto again;
- }
-}
-
-gboolean
-nm_ip6_config_commit(const NMIP6Config * self,
- NMPlatform * platform,
- NMIPRouteTableSyncMode route_table_sync,
- GPtrArray ** out_temporary_not_available)
-{
- gs_unref_ptrarray GPtrArray *addresses = NULL;
- gs_unref_ptrarray GPtrArray *routes = NULL;
- gs_unref_ptrarray GPtrArray *routes_prune = NULL;
- int ifindex;
- gboolean success = TRUE;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), FALSE);
-
- ifindex = nm_ip6_config_get_ifindex(self);
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- addresses =
- nm_dedup_multi_objs_to_ptr_array_head(nm_ip6_config_lookup_addresses(self), NULL, NULL);
-
- routes = nm_dedup_multi_objs_to_ptr_array_head(nm_ip6_config_lookup_routes(self), NULL, NULL);
-
- routes_prune =
- nm_platform_ip_route_get_prune_list(platform, AF_INET6, ifindex, route_table_sync);
-
- nm_platform_ip6_address_sync(platform, ifindex, addresses, FALSE);
-
- if (!nm_platform_ip_route_sync(platform,
- AF_INET6,
- ifindex,
- routes,
- routes_prune,
- out_temporary_not_available))
- success = FALSE;
-
- return success;
-}
-
-void
-nm_ip6_config_merge_setting(NMIP6Config * self,
- NMSettingIPConfig *setting,
- guint32 route_table,
- guint32 route_metric)
-{
- guint naddresses, nroutes, nnameservers, nsearches;
- const char * gateway_str;
- struct in6_addr gateway_bin;
- int i, priority;
-
- if (!setting)
- return;
-
- g_return_if_fail(NM_IS_SETTING_IP6_CONFIG(setting));
-
- naddresses = nm_setting_ip_config_get_num_addresses(setting);
- nroutes = nm_setting_ip_config_get_num_routes(setting);
- nnameservers = nm_setting_ip_config_get_num_dns(setting);
- nsearches = nm_setting_ip_config_get_num_dns_searches(setting);
-
- g_object_freeze_notify(G_OBJECT(self));
-
- /* Gateway */
- if (!nm_setting_ip_config_get_never_default(setting)
- && (gateway_str = nm_setting_ip_config_get_gateway(setting))
- && inet_pton(AF_INET6, gateway_str, &gateway_bin) == 1
- && !IN6_IS_ADDR_UNSPECIFIED(&gateway_bin)) {
- const NMPlatformIP6Route r = {
- .rt_source = NM_IP_CONFIG_SOURCE_USER,
- .gateway = gateway_bin,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
- };
-
- _add_route(self, NULL, &r, NULL);
- }
-
- /* Addresses */
- for (i = 0; i < naddresses; i++) {
- NMIPAddress * s_addr = nm_setting_ip_config_get_address(setting, i);
- NMPlatformIP6Address address;
-
- memset(&address, 0, sizeof(address));
- nm_ip_address_get_address_binary(s_addr, &address.address);
- address.plen = nm_ip_address_get_prefix(s_addr);
- nm_assert(address.plen <= 128);
- address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
- address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
- address.addr_source = NM_IP_CONFIG_SOURCE_USER;
-
- _add_address(self, NULL, &address);
- }
-
- /* Routes */
- for (i = 0; i < nroutes; i++) {
- NMIPRoute * s_route = nm_setting_ip_config_get_route(setting, i);
- NMPlatformIP6Route route;
- gint64 m;
-
- if (nm_ip_route_get_family(s_route) != AF_INET6) {
- nm_assert_not_reached();
- continue;
- }
-
- memset(&route, 0, sizeof(route));
- nm_ip_route_get_dest_binary(s_route, &route.network);
-
- route.plen = nm_ip_route_get_prefix(s_route);
- nm_assert(route.plen <= 128);
-
- nm_ip_route_get_next_hop_binary(s_route, &route.gateway);
- m = nm_ip_route_get_metric(s_route);
- if (m < 0)
- route.metric = route_metric;
- else
- route.metric = nm_utils_ip6_route_metric_normalize(m);
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
-
- nm_utils_ip6_address_clear_host_address(&route.network, &route.network, route.plen);
-
- nm_utils_ip_route_attribute_to_platform(AF_INET6,
- s_route,
- NM_PLATFORM_IP_ROUTE_CAST(&route),
- route_table);
- _add_route(self, NULL, &route, NULL);
- }
-
- /* DNS */
- if (nm_setting_ip_config_get_ignore_auto_dns(setting)) {
- nm_ip6_config_reset_nameservers(self);
- nm_ip6_config_reset_domains(self);
- nm_ip6_config_reset_searches(self);
- }
- for (i = 0; i < nnameservers; i++) {
- struct in6_addr ip;
-
- if (inet_pton(AF_INET6, nm_setting_ip_config_get_dns(setting, i), &ip) == 1)
- nm_ip6_config_add_nameserver(self, &ip);
- }
- for (i = 0; i < nsearches; i++)
- nm_ip6_config_add_search(self, nm_setting_ip_config_get_dns_search(setting, i));
-
- i = 0;
- while ((i = nm_setting_ip_config_next_valid_dns_option(setting, i)) >= 0) {
- nm_ip6_config_add_dns_option(self, nm_setting_ip_config_get_dns_option(setting, i));
- i++;
- }
-
- priority = nm_setting_ip_config_get_dns_priority(setting);
- if (priority)
- nm_ip6_config_set_dns_priority(self, priority);
-
- nm_ip6_config_set_never_default(self, nm_setting_ip_config_get_never_default(setting));
-
- g_object_thaw_notify(G_OBJECT(self));
-}
-
-NMSetting *
-nm_ip6_config_create_setting(const NMIP6Config *self, gboolean maybe_ipv6_disabled)
-{
- const NMIP6ConfigPrivate * priv;
- NMSettingIPConfig * s_ip6;
- guint nnameservers, nsearches, noptions;
- const char * method = NULL;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
- int i;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *address;
- const NMPlatformIP6Route * route;
-
- s_ip6 = NM_SETTING_IP_CONFIG(nm_setting_ip6_config_new());
-
- if (!self) {
- g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
- return NM_SETTING(s_ip6);
- }
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nnameservers = nm_ip6_config_get_num_nameservers(self);
- nsearches = nm_ip6_config_get_num_searches(self);
- noptions = nm_ip6_config_get_num_dns_options(self);
-
- /* Addresses */
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, self, &address) {
- NMIPAddress *s_addr;
-
- /* Ignore link-local address. */
- if (IN6_IS_ADDR_LINKLOCAL(&address->address)) {
- if (!method)
- method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
- continue;
- }
-
- /* Detect dynamic address */
- if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
- method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
- continue;
- }
-
- /* Static address found. */
- if (!method || strcmp(method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0)
- method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
-
- s_addr = nm_ip_address_new_binary(AF_INET6, &address->address, address->plen, NULL);
- nm_setting_ip_config_add_address(s_ip6, s_addr);
- nm_ip_address_unref(s_addr);
- }
-
- /* Gateway */
- if (priv->best_default_route && nm_setting_ip_config_get_num_addresses(s_ip6) > 0) {
- g_object_set(
- s_ip6,
- NM_SETTING_IP_CONFIG_GATEWAY,
- _nm_utils_inet6_ntop(&NMP_OBJECT_CAST_IP6_ROUTE(priv->best_default_route)->gateway,
- sbuf),
- NULL);
- }
-
- /* Use 'ignore' if the method wasn't previously set */
- if (!method) {
- method = maybe_ipv6_disabled ? NM_SETTING_IP6_CONFIG_METHOD_DISABLED
- : NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
- }
-
- g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, method, NULL);
-
- /* Routes */
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, &route) {
- NMIPRoute *s_route;
-
- /* Ignore link-local route. */
- if (IN6_IS_ADDR_LINKLOCAL(&route->network))
- continue;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
- continue;
-
- /* Ignore routes provided by external sources */
- if (route->rt_source
- != nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER))
- continue;
-
- s_route = nm_ip_route_new_binary(AF_INET6,
- &route->network,
- route->plen,
- &route->gateway,
- route->metric,
- NULL);
- nm_setting_ip_config_add_route(s_ip6, s_route);
- nm_ip_route_unref(s_route);
- }
-
- /* DNS */
- for (i = 0; i < nnameservers; i++) {
- const struct in6_addr *nameserver = nm_ip6_config_get_nameserver(self, i);
-
- nm_setting_ip_config_add_dns(s_ip6, _nm_utils_inet6_ntop(nameserver, sbuf));
- }
- for (i = 0; i < nsearches; i++) {
- const char *search = nm_ip6_config_get_search(self, i);
-
- nm_setting_ip_config_add_dns_search(s_ip6, search);
- }
- for (i = 0; i < noptions; i++) {
- const char *option = nm_ip6_config_get_dns_option(self, i);
-
- nm_setting_ip_config_add_dns_option(s_ip6, option);
- }
-
- g_object_set(s_ip6,
- NM_SETTING_IP_CONFIG_DNS_PRIORITY,
- nm_ip6_config_get_dns_priority(self),
- NULL);
-
- return NM_SETTING(s_ip6);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_merge(NMIP6Config * dst,
- const NMIP6Config * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty)
-{
- guint32 i;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *address = NULL;
- const NMIP6ConfigPrivate * src_priv;
-
- g_return_if_fail(src != NULL);
- g_return_if_fail(dst != NULL);
-
- src_priv = NM_IP6_CONFIG_GET_PRIVATE(src);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, src, &address) {
- if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_EXTERNAL) && !address->external) {
- NMPlatformIP6Address a;
-
- a = *address;
- a.external = TRUE;
- _add_address(dst, NULL, &a);
- } else
- _add_address(dst, NMP_OBJECT_UP_CAST(address), NULL);
- }
-
- /* nameservers */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip6_config_get_num_nameservers(src); i++)
- nm_ip6_config_add_nameserver(dst, nm_ip6_config_get_nameserver(src, i));
- }
-
- /* routes */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
- const NMPlatformIP6Route *r_src;
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &r_src) {
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) {
- if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES)
- && !NM_FLAGS_HAS(src_priv->config_flags,
- NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES))
- continue;
- if (default_route_metric_penalty) {
- NMPlatformIP6Route r = *r_src;
-
- r.metric =
- nm_utils_ip_route_metric_penalize(r.metric, default_route_metric_penalty);
- _add_route(dst, NULL, &r, NULL);
- continue;
- }
- }
- _add_route(dst, ipconf_iter.current->obj, NULL, NULL);
- }
- }
-
- /* domains */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip6_config_get_num_domains(src); i++)
- nm_ip6_config_add_domain(dst, nm_ip6_config_get_domain(src, i));
- }
-
- /* dns searches */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip6_config_get_num_searches(src); i++)
- nm_ip6_config_add_search(dst, nm_ip6_config_get_search(src, i));
- }
-
- /* dns options */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip6_config_get_num_dns_options(src); i++)
- nm_ip6_config_add_dns_option(dst, nm_ip6_config_get_dns_option(src, i));
- }
-
- /* DNS priority */
- if (nm_ip6_config_get_dns_priority(src))
- nm_ip6_config_set_dns_priority(dst, nm_ip6_config_get_dns_priority(src));
-
- g_object_thaw_notify(G_OBJECT(dst));
-}
-
-/*****************************************************************************/
-
-static int
-_nameservers_get_index(const NMIP6Config *self, const struct in6_addr *ns)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->nameservers->len; i++) {
- const struct in6_addr *n = &g_array_index(priv->nameservers, struct in6_addr, i);
-
- if (IN6_ARE_ADDR_EQUAL(ns, n))
- return (int) i;
- }
- return -1;
-}
-
-static int
-_domains_get_index(const NMIP6Config *self, const char *domain)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->domains->len; i++) {
- const char *d = g_ptr_array_index(priv->domains, i);
-
- if (g_strcmp0(domain, d) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_searches_get_index(const NMIP6Config *self, const char *search)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->searches->len; i++) {
- const char *s = g_ptr_array_index(priv->searches, i);
-
- if (g_strcmp0(search, s) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_dns_options_get_index(const NMIP6Config *self, const char *option)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->dns_options->len; i++) {
- const char *s = g_ptr_array_index(priv->dns_options, i);
-
- if (g_strcmp0(option, s) == 0)
- return (int) i;
- }
- return -1;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_ip6_config_subtract:
- * @dst: config from which to remove everything in @src
- * @src: config to remove from @dst
- * @default_route_metric_penalty: pretend that on source we applied
- * a route penalty on the default-route. It means, for default routes
- * we don't remove routes that match exactly, but those with a lower
- * metric (with the penalty removed).
-*
- * Removes everything in @src from @dst.
- */
-void
-nm_ip6_config_subtract(NMIP6Config * dst,
- const NMIP6Config *src,
- guint32 default_route_metric_penalty)
-{
- NMIP6ConfigPrivate * dst_priv;
- guint i;
- int idx;
- const NMPlatformIP6Address *a;
- const NMPlatformIP6Route * r;
- NMDedupMultiIter ipconf_iter;
- gboolean changed;
- gboolean changed_default_route;
-
- g_return_if_fail(src != NULL);
- g_return_if_fail(dst != NULL);
-
- dst_priv = NM_IP6_CONFIG_GET_PRIVATE(dst);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- changed = FALSE;
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, src, &a) {
- if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip6_addresses,
- NMP_OBJECT_UP_CAST(a),
- NULL))
- changed = TRUE;
- }
- if (changed)
- _notify_addresses(dst);
-
- /* nameservers */
- for (i = 0; i < nm_ip6_config_get_num_nameservers(src); i++) {
- idx = _nameservers_get_index(dst, nm_ip6_config_get_nameserver(src, i));
- if (idx >= 0)
- nm_ip6_config_del_nameserver(dst, idx);
- }
-
- /* routes */
- changed = FALSE;
- changed_default_route = FALSE;
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &r) {
- const NMPObject * o_src = NMP_OBJECT_UP_CAST(r);
- NMPObject o_lookup_copy;
- const NMPObject * o_lookup;
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
- NMPlatformIP6Route *rr;
-
- /* the default route was penalized when merging it to the combined ip-config.
- * When subtracting the routes, we must re-do that process when comparing
- * the routes. */
- o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_src);
- rr = NMP_OBJECT_CAST_IP6_ROUTE(&o_lookup_copy);
- rr->metric =
- nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
- } else
- o_lookup = o_src;
-
- if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip6_routes,
- o_lookup,
- (gconstpointer *) &obj_old)) {
- if (dst_priv->best_default_route == obj_old) {
- nm_clear_nmp_object(&dst_priv->best_default_route);
- changed_default_route = TRUE;
- }
- changed = TRUE;
- }
- }
- if (changed_default_route) {
- nmp_object_ref_set(&dst_priv->best_default_route,
- _nm_ip6_config_best_default_route_find(dst));
- _notify(dst, PROP_GATEWAY);
- }
- if (changed)
- _notify_routes(dst);
-
- /* domains */
- for (i = 0; i < nm_ip6_config_get_num_domains(src); i++) {
- idx = _domains_get_index(dst, nm_ip6_config_get_domain(src, i));
- if (idx >= 0)
- nm_ip6_config_del_domain(dst, idx);
- }
-
- /* dns searches */
- for (i = 0; i < nm_ip6_config_get_num_searches(src); i++) {
- idx = _searches_get_index(dst, nm_ip6_config_get_search(src, i));
- if (idx >= 0)
- nm_ip6_config_del_search(dst, idx);
- }
-
- /* dns options */
- for (i = 0; i < nm_ip6_config_get_num_dns_options(src); i++) {
- idx = _dns_options_get_index(dst, nm_ip6_config_get_dns_option(src, i));
- if (idx >= 0)
- nm_ip6_config_del_dns_option(dst, idx);
- }
-
- /* DNS priority */
- if (nm_ip6_config_get_dns_priority(src) == nm_ip6_config_get_dns_priority(dst))
- nm_ip6_config_set_dns_priority(dst, 0);
-
- g_object_thaw_notify(G_OBJECT(dst));
-}
-
-static gboolean
-_nm_ip6_config_intersect_helper(NMIP6Config * dst,
- const NMIP6Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty,
- gboolean update_dst)
-{
- NMIP6ConfigPrivate * dst_priv;
- const NMIP6ConfigPrivate * src_priv;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *a;
- const NMPlatformIP6Route * r;
- gboolean changed, result = FALSE;
- const NMPObject * new_best_default_route;
-
- g_return_val_if_fail(src, FALSE);
- g_return_val_if_fail(dst, FALSE);
-
- dst_priv = NM_IP6_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP6_CONFIG_GET_PRIVATE(src);
-
- if (update_dst)
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- if (intersect_addresses) {
- changed = FALSE;
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, dst, &a) {
- if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
- &src_priv->idx_ip6_addresses,
- NMP_OBJECT_UP_CAST(a)))
- continue;
-
- if (!update_dst)
- return TRUE;
-
- if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
- nm_assert_not_reached();
- changed = TRUE;
- }
- if (changed) {
- _notify_addresses(dst);
- result = TRUE;
- }
- }
-
- /* ignore nameservers */
-
- /* routes */
- if (!intersect_routes)
- goto skip_routes;
-
- changed = FALSE;
- new_best_default_route = NULL;
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, dst, &r) {
- const NMPObject *o_dst = NMP_OBJECT_UP_CAST(r);
- const NMPObject *o_lookup;
- NMPObject o_lookup_copy;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
- NMPlatformIP6Route *rr;
-
- /* the default route was penalized when merging it to the combined ip-config.
- * When intersecting the routes, we must re-do that process when comparing
- * the routes. */
- o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_dst);
- rr = NMP_OBJECT_CAST_IP6_ROUTE(&o_lookup_copy);
- rr->metric =
- nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
- } else
- o_lookup = o_dst;
-
- if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
- &src_priv->idx_ip6_routes,
- o_lookup)) {
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, o_dst);
- continue;
- }
-
- if (!update_dst)
- return TRUE;
-
- if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
- nm_assert_not_reached();
- changed = TRUE;
- }
- if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route)) {
- nm_assert(changed);
- _notify(dst, PROP_GATEWAY);
- }
- if (changed) {
- _notify_routes(dst);
- result = TRUE;
- }
-
-skip_routes:
- /* ignore domains */
- /* ignore dns searches */
- /* ignore dns options */
-
- if (update_dst)
- g_object_thaw_notify(G_OBJECT(dst));
-
- return result;
-}
-
-/**
- * nm_ip6_config_intersect:
- * @dst: a configuration to be updated
- * @src: another configuration
- * @intersect_addresses: whether addresses should be intersected
- * @intersect_routes: whether routes should be intersected
- * @default_route_metric_penalty: the default route metric penalty
- *
- * Computes the intersection between @src and @dst and updates @dst in place
- * with the result.
- */
-void
-nm_ip6_config_intersect(NMIP6Config * dst,
- const NMIP6Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- _nm_ip6_config_intersect_helper(dst,
- src,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- TRUE);
-}
-
-/**
- * nm_ip6_config_intersect_alloc:
- * @a: a configuration
- * @b: another configuration
- * @intersect_addresses: whether addresses should be intersected
- * @intersect_routes: whether routes should be intersected
- * @default_route_metric_penalty: the default route metric penalty
- *
- * Computes the intersection between @a and @b and returns the result in a newly
- * allocated configuration. As a special case, if @a and @b are identical (with
- * respect to the only properties considered - addresses and routes) the
- * functions returns NULL so that one of existing configuration can be reused
- * without allocation.
- *
- * Returns: the intersection between @a and @b, or %NULL if the result is equal
- * to @a and @b.
- */
-NMIP6Config *
-nm_ip6_config_intersect_alloc(const NMIP6Config *a,
- const NMIP6Config *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- NMIP6Config *a_copy;
-
- if (_nm_ip6_config_intersect_helper((NMIP6Config *) a,
- b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- FALSE)) {
- a_copy = nm_ip6_config_clone(a);
- _nm_ip6_config_intersect_helper(a_copy,
- b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- TRUE);
- return a_copy;
- } else
- return NULL;
-}
-
-/**
- * nm_ip6_config_replace:
- * @dst: config which will be replaced with everything in @src
- * @src: config to copy over to @dst
- * @relevant_changes: return whether there are changes to the
- * destination object that are relevant. This is equal to
- * nm_ip6_config_equal() showing any difference.
- *
- * Replaces everything in @dst with @src so that the two configurations
- * contain the same content -- with the exception of the dbus path.
- *
- * Returns: whether the @dst instance changed in any way (including minor changes,
- * that are not signaled by the output parameter @relevant_changes).
- */
-gboolean
-nm_ip6_config_replace(NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes)
-{
-#if NM_MORE_ASSERTS
- gboolean config_equal;
-#endif
- gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal;
- guint i, num;
- NMIP6ConfigPrivate * dst_priv;
- const NMIP6ConfigPrivate * src_priv;
- NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst;
- const NMDedupMultiHeadEntry *head_entry_src;
- const NMPObject * new_best_default_route;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(src), FALSE);
- g_return_val_if_fail(NM_IS_IP6_CONFIG(dst), FALSE);
- g_return_val_if_fail(src != dst, FALSE);
-
-#if NM_MORE_ASSERTS
- config_equal = nm_ip6_config_equal(dst, src);
-#endif
-
- dst_priv = NM_IP6_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP6_CONFIG_GET_PRIVATE(src);
-
- g_return_val_if_fail(src_priv->ifindex > 0, FALSE);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* ifindex */
- if (src_priv->ifindex != dst_priv->ifindex) {
- dst_priv->ifindex = src_priv->ifindex;
- has_minor_changes = TRUE;
- }
-
- /* addresses */
- head_entry_src = nm_ip6_config_lookup_addresses(src);
- nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
- nm_ip_config_iter_ip6_address_init(&ipconf_iter_dst, dst);
- are_equal = TRUE;
- while (TRUE) {
- gboolean has;
- const NMPlatformIP6Address *r_src = NULL;
- const NMPlatformIP6Address *r_dst = NULL;
-
- has = nm_platform_dedup_multi_iter_next_ip6_address(&ipconf_iter_src, &r_src);
- if (has != nm_platform_dedup_multi_iter_next_ip6_address(&ipconf_iter_dst, &r_dst)) {
- are_equal = FALSE;
- has_relevant_changes = TRUE;
- break;
- }
- if (!has)
- break;
-
- if (nm_platform_ip6_address_cmp(r_src, r_dst) != 0) {
- are_equal = FALSE;
- if (!IN6_ARE_ADDR_EQUAL(&r_src->address, &r_dst->address) || r_src->plen != r_dst->plen
- || !IN6_ARE_ADDR_EQUAL(nm_platform_ip6_address_get_peer(r_src),
- nm_platform_ip6_address_get_peer(r_dst))) {
- has_relevant_changes = TRUE;
- break;
- }
- }
- }
- if (!are_equal) {
- has_minor_changes = TRUE;
- nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip6_addresses);
- nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
- _nm_ip_config_add_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip6_addresses_,
- dst_priv->ifindex,
- ipconf_iter_src.current->obj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL);
- }
- nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
- &dst_priv->idx_ip6_addresses,
- FALSE);
- _notify_addresses(dst);
- }
-
- /* routes */
- head_entry_src = nm_ip6_config_lookup_routes(src);
- nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
- nm_ip_config_iter_ip6_route_init(&ipconf_iter_dst, dst);
- are_equal = TRUE;
- while (TRUE) {
- gboolean has;
- const NMPlatformIP6Route *r_src = NULL;
- const NMPlatformIP6Route *r_dst = NULL;
-
- has = nm_platform_dedup_multi_iter_next_ip6_route(&ipconf_iter_src, &r_src);
- if (has != nm_platform_dedup_multi_iter_next_ip6_route(&ipconf_iter_dst, &r_dst)) {
- are_equal = FALSE;
- has_relevant_changes = TRUE;
- break;
- }
- if (!has)
- break;
-
- if (nm_platform_ip6_route_cmp_full(r_src, r_dst) != 0) {
- are_equal = FALSE;
- if (r_src->plen != r_dst->plen
- || !nm_utils_ip6_address_same_prefix(&r_src->network, &r_dst->network, r_src->plen)
- || r_src->metric != r_dst->metric
- || !IN6_ARE_ADDR_EQUAL(&r_src->gateway, &r_dst->gateway)) {
- has_relevant_changes = TRUE;
- break;
- }
- }
- }
- if (!are_equal) {
- has_minor_changes = TRUE;
- new_best_default_route = NULL;
- nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip6_routes);
- nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
- const NMPObject *o = ipconf_iter_src.current->obj;
- const NMPObject *obj_new;
-
- _nm_ip_config_add_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip6_routes_,
- dst_priv->ifindex,
- o,
- NULL,
- FALSE,
- TRUE,
- NULL,
- &obj_new);
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new);
- }
- nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
- &dst_priv->idx_ip6_routes,
- FALSE);
- if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route))
- _notify(dst, PROP_GATEWAY);
- _notify_routes(dst);
- }
-
- /* nameservers */
- num = nm_ip6_config_get_num_nameservers(src);
- are_equal = num == nm_ip6_config_get_num_nameservers(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (!IN6_ARE_ADDR_EQUAL(nm_ip6_config_get_nameserver(src, i),
- nm_ip6_config_get_nameserver(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip6_config_reset_nameservers(dst);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_nameserver(dst, nm_ip6_config_get_nameserver(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* domains */
- num = nm_ip6_config_get_num_domains(src);
- are_equal = num == nm_ip6_config_get_num_domains(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip6_config_get_domain(src, i), nm_ip6_config_get_domain(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip6_config_reset_domains(dst);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_domain(dst, nm_ip6_config_get_domain(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* dns searches */
- num = nm_ip6_config_get_num_searches(src);
- are_equal = num == nm_ip6_config_get_num_searches(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip6_config_get_search(src, i), nm_ip6_config_get_search(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip6_config_reset_searches(dst);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_search(dst, nm_ip6_config_get_search(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* dns options */
- num = nm_ip6_config_get_num_dns_options(src);
- are_equal = num == nm_ip6_config_get_num_dns_options(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip6_config_get_dns_option(src, i),
- nm_ip6_config_get_dns_option(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip6_config_reset_dns_options(dst);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_dns_option(dst, nm_ip6_config_get_dns_option(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* DNS priority */
- if (src_priv->dns_priority != dst_priv->dns_priority) {
- nm_ip6_config_set_dns_priority(dst, src_priv->dns_priority);
- has_minor_changes = TRUE;
- }
-
- if (src_priv->privacy != dst_priv->privacy) {
- nm_ip6_config_set_privacy(dst, src_priv->privacy);
- has_minor_changes = TRUE;
- }
-
-#if NM_MORE_ASSERTS
- /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes
- * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
- nm_assert(config_equal == !has_relevant_changes);
-#endif
-
- g_object_thaw_notify(G_OBJECT(dst));
-
- if (relevant_changes)
- *relevant_changes = has_relevant_changes;
-
- return has_relevant_changes || has_minor_changes;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_addresses_ndisc(NMIP6Config * self,
- const NMNDiscAddress *addresses,
- guint addresses_n,
- guint8 plen,
- guint32 ifa_flags)
-{
- NMIP6ConfigPrivate *priv;
- guint i;
- gboolean changed = FALSE;
- gint32 base_time_sec;
-
- g_return_if_fail(NM_IS_IP6_CONFIG(self));
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(priv->ifindex > 0);
-
- /* the base-timestamp doesn't matter it's only an anchor for the
- * expiry. However, try to re-use the same base-time for a while
- * by rounding it to 10000 seconds.
- *
- * That is because we deduplicate and NMPlatformIP6Address instances
- * so using the same timestamps is preferable. */
- base_time_sec = nm_utils_get_monotonic_timestamp_sec();
- base_time_sec = (base_time_sec / 10000) * 10000;
- base_time_sec = NM_MAX(1, base_time_sec);
-
- nm_dedup_multi_index_dirty_set_idx(priv->multi_idx, &priv->idx_ip6_addresses);
-
- for (i = 0; i < addresses_n; i++) {
- const NMNDiscAddress *ndisc_addr = &addresses[i];
- NMPObject obj;
- NMPlatformIP6Address *a;
-
- nmp_object_stackinit(&obj, NMP_OBJECT_TYPE_IP6_ADDRESS, NULL);
- a = NMP_OBJECT_CAST_IP6_ADDRESS(&obj);
- a->ifindex = priv->ifindex;
- a->address = ndisc_addr->address;
- a->plen = plen;
- a->timestamp = base_time_sec,
- a->lifetime = _nm_ndisc_lifetime_from_expiry(((gint64) base_time_sec) * 1000,
- ndisc_addr->expiry_msec,
- TRUE),
- a->preferred = _nm_ndisc_lifetime_from_expiry(((gint64) base_time_sec) * 1000,
- ndisc_addr->expiry_preferred_msec,
- TRUE),
- a->addr_source = NM_IP_CONFIG_SOURCE_NDISC;
- a->n_ifa_flags = ifa_flags;
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_addresses_,
- priv->ifindex,
- &obj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL))
- changed = TRUE;
- }
-
- if (nm_dedup_multi_index_dirty_remove_idx(priv->multi_idx, &priv->idx_ip6_addresses, FALSE) > 0)
- changed = TRUE;
-
- if (changed)
- _notify_addresses(self);
-}
-
-void
-nm_ip6_config_reset_addresses(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip6_addresses) > 0)
- _notify_addresses(self);
-}
-
-static void
-_add_address(NMIP6Config *self, const NMPObject *obj_new, const NMPlatformIP6Address *new)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_addresses_,
- priv->ifindex,
- obj_new,
- (const NMPlatformObject *) new,
- TRUE,
- FALSE,
- NULL,
- NULL))
- _notify_addresses(self);
-}
-
-/**
- * nm_ip6_config_add_address:
- * @self: the #NMIP6Config
- * @new: the new address to add to @self
- *
- * Adds the new address to @self. If an address with the same basic properties
- * (address, prefix) already exists in @self, it is overwritten with the
- * lifetime and preferred of @new. The source is also overwritten by the source
- * from @new if that source is higher priority.
- */
-void
-nm_ip6_config_add_address(NMIP6Config *self, const NMPlatformIP6Address *new)
-{
- g_return_if_fail(self);
- g_return_if_fail(new);
- g_return_if_fail(new->plen <= 128);
- g_return_if_fail(NM_IP6_CONFIG_GET_PRIVATE(self)->ifindex > 0);
-
- _add_address(self, NULL, new);
-}
-
-void
-_nmtst_ip6_config_del_address(NMIP6Config *self, guint i)
-{
- const NMPlatformIP6Address *a;
-
- a = _nmtst_ip6_config_get_address(self, i);
- if (!nm_ip6_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(a)))
- g_assert_not_reached();
-}
-
-guint
-nm_ip6_config_get_num_addresses(const NMIP6Config *self)
-{
- const NMDedupMultiHeadEntry *head_entry;
-
- head_entry = nm_ip6_config_lookup_addresses(self);
- return head_entry ? head_entry->len : 0;
-}
-
-const NMPlatformIP6Address *
-nm_ip6_config_get_first_address(const NMIP6Config *self)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP6Address *a = NULL;
-
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &a)
- return a;
- return NULL;
-}
-
-const NMPlatformIP6Address *
-_nmtst_ip6_config_get_address(const NMIP6Config *self, guint i)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP6Address *a = NULL;
- guint j;
-
- j = 0;
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &a) {
- if (i == j)
- return a;
- j++;
- }
- g_return_val_if_reached(NULL);
-}
-
-const NMPlatformIP6Address *
-nm_ip6_config_lookup_address(const NMIP6Config *self, const struct in6_addr *addr)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- NMPObject obj_stack;
- const NMDedupMultiEntry * entry;
-
- nmp_object_stackinit_id_ip6_address(&obj_stack, priv->ifindex, addr);
- entry = nm_dedup_multi_index_lookup_obj(priv->multi_idx, &priv->idx_ip6_addresses, &obj_stack);
- return entry ? NMP_OBJECT_CAST_IP6_ADDRESS(entry->obj) : NULL;
-}
-
-/**
- * nm_ip6_config_has_dad_pending_addresses
- * @self: configuration containing the addresses to check
- * @candidates: configuration with the list of addresses we are
- * interested in
- *
- * Check whether there are addresses with DAD pending in @self, that
- * are also contained in @candidates.
- *
- * Returns: %TRUE if at least one matching address was found, %FALSE
- * otherwise
- */
-gboolean
-nm_ip6_config_has_any_dad_pending(const NMIP6Config *self, const NMIP6Config *candidates)
-{
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *addr, *addr_c;
-
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, self, &addr) {
- if (NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_TENTATIVE)
- && !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_DADFAILED)
- && !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_OPTIMISTIC)) {
- addr_c = nm_ip6_config_lookup_address(candidates, &addr->address);
- if (addr_c) {
- if (addr->plen == addr_c->plen)
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static const NMDedupMultiEntry *
-_lookup_route(const NMIP6Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type)
-{
- const NMIP6ConfigPrivate *priv;
-
- nm_assert(NM_IS_IP6_CONFIG(self));
- nm_assert(NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP6_ROUTE);
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return _nm_ip_config_lookup_ip_route(priv->multi_idx, &priv->idx_ip6_routes_, needle, cmp_type);
-}
-
-void
-nm_ip6_config_reset_routes_ndisc(NMIP6Config * self,
- const NMNDiscGateway *gateways,
- guint gateways_n,
- const NMNDiscRoute * routes,
- guint routes_n,
- guint32 route_table,
- guint32 route_metric)
-{
- NMIP6ConfigPrivate *priv;
- guint i;
- gboolean changed = FALSE;
- const NMPObject * new_best_default_route;
-
- g_return_if_fail(NM_IS_IP6_CONFIG(self));
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(priv->ifindex > 0);
-
- nm_dedup_multi_index_dirty_set_idx(priv->multi_idx, &priv->idx_ip6_routes);
-
- new_best_default_route = NULL;
- for (i = 0; i < routes_n; i++) {
- const NMNDiscRoute *ndisc_route = &routes[i];
- NMPObject obj;
- const NMPObject * obj_new;
- NMPlatformIP6Route *r;
-
- nmp_object_stackinit(&obj, NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
- r = NMP_OBJECT_CAST_IP6_ROUTE(&obj);
- r->ifindex = priv->ifindex;
- r->network = ndisc_route->network;
- r->plen = ndisc_route->plen;
- r->gateway = ndisc_route->gateway;
- r->rt_source = NM_IP_CONFIG_SOURCE_NDISC;
- r->table_coerced = nm_platform_route_table_coerce(route_table);
- r->metric = route_metric;
- r->rt_pref = ndisc_route->preference;
- nm_assert((NMIcmpv6RouterPref) r->rt_pref == ndisc_route->preference);
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_routes_,
- priv->ifindex,
- &obj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- &obj_new))
- changed = TRUE;
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new);
- }
-
- if (gateways_n) {
- const NMPObject * obj_new;
- NMPlatformIP6Route r = {
- .rt_source = NM_IP_CONFIG_SOURCE_NDISC,
- .ifindex = priv->ifindex,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
- };
-
- for (i = 0; i < gateways_n; i++) {
- r.gateway = gateways[i].address;
- r.rt_pref = gateways[i].preference;
- nm_assert((NMIcmpv6RouterPref) r.rt_pref == gateways[i].preference);
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_routes_,
- priv->ifindex,
- NULL,
- (const NMPlatformObject *) &r,
- FALSE,
- TRUE,
- NULL,
- &obj_new))
- changed = TRUE;
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new);
- }
- }
-
- if (nm_dedup_multi_index_dirty_remove_idx(priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0)
- changed = TRUE;
-
- if (nmp_object_ref_set(&priv->best_default_route, new_best_default_route)) {
- changed = TRUE;
- _notify(self, PROP_GATEWAY);
- }
-
- if (changed)
- _notify_routes(self);
-}
-
-void
-nm_ip6_config_reset_routes(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip6_routes) > 0) {
- if (nm_clear_nmp_object(&priv->best_default_route))
- _notify(self, PROP_GATEWAY);
- _notify_routes(self);
- }
-}
-
-static void
-_add_route(NMIP6Config * self,
- const NMPObject *obj_new,
- const NMPlatformIP6Route *new,
- const NMPObject **out_obj_new)
-{
- NMIP6ConfigPrivate * priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
- const NMPObject * obj_new_2;
-
- nm_assert((!new) != (!obj_new));
- nm_assert(!new || _route_valid(new));
- nm_assert(!obj_new || _route_valid(NMP_OBJECT_CAST_IP6_ROUTE(obj_new)));
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_routes_,
- priv->ifindex,
- obj_new,
- (const NMPlatformObject *) new,
- TRUE,
- FALSE,
- &obj_old,
- &obj_new_2)) {
- gboolean changed_default_route = FALSE;
-
- if (priv->best_default_route == obj_old && obj_old != obj_new_2) {
- changed_default_route = TRUE;
- nm_clear_nmp_object(&priv->best_default_route);
- }
- NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
- if (_nm_ip_config_best_default_route_merge(&priv->best_default_route, obj_new_2))
- changed_default_route = TRUE;
-
- if (changed_default_route)
- _notify(self, PROP_GATEWAY);
- _notify_routes(self);
- } else
- NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
-}
-
-/**
- * nm_ip6_config_add_route:
- * @self: the #NMIP6Config
- * @new: the new route to add to @self
- * @out_obj_new: (allow-none) (out): the added route object. Must be unrefed
- * by caller.
- *
- * Adds the new route to @self. If a route with the same basic properties
- * (network, prefix) already exists in @self, it is overwritten including the
- * gateway and metric of @new. The source is also overwritten by the source
- * from @new if that source is higher priority.
- */
-void
-nm_ip6_config_add_route(NMIP6Config *self,
- const NMPlatformIP6Route *new,
- const NMPObject **out_obj_new)
-{
- g_return_if_fail(self);
- g_return_if_fail(new);
- g_return_if_fail(new->plen <= 128);
- g_return_if_fail(NM_IP6_CONFIG_GET_PRIVATE(self)->ifindex > 0);
-
- _add_route(self, NULL, new, out_obj_new);
-}
-
-void
-_nmtst_ip6_config_del_route(NMIP6Config *self, guint i)
-{
- const NMPlatformIP6Route *r;
-
- r = _nmtst_ip6_config_get_route(self, i);
- if (!nm_ip6_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(r)))
- g_assert_not_reached();
-}
-
-guint
-nm_ip6_config_get_num_routes(const NMIP6Config *self)
-{
- const NMDedupMultiHeadEntry *head_entry;
-
- head_entry = nm_ip6_config_lookup_routes(self);
- nm_assert(!head_entry || head_entry->len == c_list_length(&head_entry->lst_entries_head));
- return head_entry ? head_entry->len : 0;
-}
-
-const NMPlatformIP6Route *
-_nmtst_ip6_config_get_route(const NMIP6Config *self, guint i)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP6Route *r = NULL;
- guint j;
-
- j = 0;
- nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) {
- if (i == j)
- return r;
- j++;
- }
- g_return_val_if_reached(NULL);
-}
-
-const NMPlatformIP6Route *
-nm_ip6_config_get_direct_route_for_host(const NMIP6Config * self,
- const struct in6_addr *host,
- guint32 route_table)
-{
- const NMPlatformIP6Route *best_route = NULL;
- const NMPlatformIP6Route *item;
- NMDedupMultiIter ipconf_iter;
-
- g_return_val_if_fail(host && !IN6_IS_ADDR_UNSPECIFIED(host), NULL);
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, &item) {
- if (!IN6_IS_ADDR_UNSPECIFIED(&item->gateway))
- continue;
-
- if (best_route && best_route->plen > item->plen)
- continue;
-
- if (nm_platform_route_table_uncoerce(item->table_coerced, TRUE) != route_table)
- continue;
-
- if (!nm_utils_ip6_address_same_prefix(host, &item->network, item->plen))
- continue;
-
- if (best_route && best_route->metric <= item->metric)
- continue;
-
- best_route = item;
- }
- return best_route;
-}
-
-const NMPlatformIP6Address *
-nm_ip6_config_get_subnet_for_host(const NMIP6Config *self, const struct in6_addr *host)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP6Address *item;
- const NMPlatformIP6Address *subnet = NULL;
- struct in6_addr subnet2, host2;
-
- g_return_val_if_fail(host && !IN6_IS_ADDR_UNSPECIFIED(host), NULL);
-
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &item) {
- if (subnet && subnet->plen >= item->plen)
- continue;
-
- nm_utils_ip6_address_clear_host_address(&host2, host, item->plen);
- nm_utils_ip6_address_clear_host_address(&subnet2, &item->address, item->plen);
-
- if (IN6_ARE_ADDR_EQUAL(&subnet2, &host2))
- subnet = item;
- }
-
- return subnet;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_nameservers(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priv->nameservers->len != 0) {
- g_array_set_size(priv->nameservers, 0);
- _notify(self, PROP_NAMESERVERS);
- }
-}
-
-void
-nm_ip6_config_add_nameserver(NMIP6Config *self, const struct in6_addr *new)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(new != NULL);
-
- for (i = 0; i < priv->nameservers->len; i++)
- if (IN6_ARE_ADDR_EQUAL(new, &g_array_index(priv->nameservers, struct in6_addr, i)))
- return;
-
- g_array_append_val(priv->nameservers, *new);
- _notify(self, PROP_NAMESERVERS);
-}
-
-void
-nm_ip6_config_del_nameserver(NMIP6Config *self, guint i)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->nameservers->len);
-
- g_array_remove_index(priv->nameservers, i);
- _notify(self, PROP_NAMESERVERS);
-}
-
-guint
-nm_ip6_config_get_num_nameservers(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->nameservers->len;
-}
-
-const struct in6_addr *
-nm_ip6_config_get_nameserver(const NMIP6Config *self, guint i)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return &g_array_index(priv->nameservers, struct in6_addr, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_domains(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priv->domains->len != 0) {
- g_ptr_array_set_size(priv->domains, 0);
- _notify(self, PROP_DOMAINS);
- }
-}
-
-void
-nm_ip6_config_add_domain(NMIP6Config *self, const char *domain)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_check_and_add_domain(priv->domains, domain))
- _notify(self, PROP_DOMAINS);
-}
-
-void
-nm_ip6_config_del_domain(NMIP6Config *self, guint i)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->domains->len);
-
- g_ptr_array_remove_index(priv->domains, i);
- _notify(self, PROP_DOMAINS);
-}
-
-guint
-nm_ip6_config_get_num_domains(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->domains->len;
-}
-
-const char *
-nm_ip6_config_get_domain(const NMIP6Config *self, guint i)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->domains, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_searches(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priv->searches->len != 0) {
- g_ptr_array_set_size(priv->searches, 0);
- _notify(self, PROP_SEARCHES);
- }
-}
-
-void
-nm_ip6_config_add_search(NMIP6Config *self, const char *search)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_check_and_add_domain(priv->searches, search))
- _notify(self, PROP_SEARCHES);
-}
-
-void
-nm_ip6_config_del_search(NMIP6Config *self, guint i)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->searches->len);
-
- g_ptr_array_remove_index(priv->searches, i);
- _notify(self, PROP_SEARCHES);
-}
-
-guint
-nm_ip6_config_get_num_searches(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->searches->len;
-}
-
-const char *
-nm_ip6_config_get_search(const NMIP6Config *self, guint i)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->searches, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_dns_options(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priv->dns_options->len != 0) {
- g_ptr_array_set_size(priv->dns_options, 0);
- _notify(self, PROP_DNS_OPTIONS);
- }
-}
-
-void
-nm_ip6_config_add_dns_option(NMIP6Config *self, const char *new)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(new != NULL);
- g_return_if_fail(new[0] != '\0');
-
- for (i = 0; i < priv->dns_options->len; i++)
- if (!g_strcmp0(g_ptr_array_index(priv->dns_options, i), new))
- return;
-
- g_ptr_array_add(priv->dns_options, g_strdup(new));
- _notify(self, PROP_DNS_OPTIONS);
-}
-
-void
-nm_ip6_config_del_dns_option(NMIP6Config *self, guint i)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->dns_options->len);
-
- g_ptr_array_remove_index(priv->dns_options, i);
- _notify(self, PROP_DNS_OPTIONS);
-}
-
-guint
-nm_ip6_config_get_num_dns_options(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->dns_options->len;
-}
-
-const char *
-nm_ip6_config_get_dns_option(const NMIP6Config *self, guint i)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->dns_options, i);
-}
-
-/*****************************************************************************/
-
-NMIPConfigFlags
-nm_ip6_config_get_config_flags(const NMIP6Config *self)
-{
- return NM_IP6_CONFIG_GET_PRIVATE(self)->config_flags;
-}
-
-void
-nm_ip6_config_set_config_flags(NMIP6Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (mask == 0) {
- /* for convenience, accept 0 mask to set any flags. */
- mask = flags;
- }
-
- nm_assert(!NM_FLAGS_ANY(flags, ~mask));
- priv->config_flags = (flags & mask) | (priv->config_flags & ~mask);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_set_dns_priority(NMIP6Config *self, int priority)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priority != priv->dns_priority) {
- priv->dns_priority = priority;
- _notify(self, PROP_DNS_PRIORITY);
- }
-}
-
-int
-nm_ip6_config_get_dns_priority(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->dns_priority;
-}
-
-/*****************************************************************************/
-
-const NMPObject *
-nm_ip6_config_nmpobj_lookup(const NMIP6Config *self, const NMPObject *needle)
-{
- const NMIP6ConfigPrivate * priv;
- const NMDedupMultiIdxType *idx_type;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), NULL);
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- switch (NMP_OBJECT_GET_TYPE(needle)) {
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- idx_type = &priv->idx_ip6_addresses;
- break;
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- idx_type = &priv->idx_ip6_routes;
- break;
- default:
- g_return_val_if_reached(NULL);
- }
-
- return nm_dedup_multi_entry_get_obj(
- nm_dedup_multi_index_lookup_obj(priv->multi_idx, idx_type, needle));
-}
-
-gboolean
-nm_ip6_config_nmpobj_remove(NMIP6Config *self, const NMPObject *needle)
-{
- NMIP6ConfigPrivate * priv;
- NMDedupMultiIdxType *idx_type;
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
- guint n;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), FALSE);
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- switch (NMP_OBJECT_GET_TYPE(needle)) {
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- idx_type = &priv->idx_ip6_addresses;
- break;
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- idx_type = &priv->idx_ip6_routes;
- break;
- default:
- g_return_val_if_reached(FALSE);
- }
-
- n = nm_dedup_multi_index_remove_obj(priv->multi_idx,
- idx_type,
- needle,
- (gconstpointer *) &obj_old);
- if (n != 1) {
- nm_assert(n == 0);
- return FALSE;
- }
-
- nm_assert(NMP_OBJECT_GET_TYPE(obj_old) == NMP_OBJECT_GET_TYPE(needle));
-
- switch (NMP_OBJECT_GET_TYPE(obj_old)) {
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- _notify_addresses(self);
- break;
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- if (priv->best_default_route == obj_old) {
- if (nmp_object_ref_set(&priv->best_default_route,
- _nm_ip6_config_best_default_route_find(self)))
- _notify(self, PROP_GATEWAY);
- }
- _notify_routes(self);
- break;
- default:
- nm_assert_not_reached();
- }
- return TRUE;
-}
-
-/*****************************************************************************/
-
-static void
-hash_u32(GChecksum *sum, guint32 n)
-{
- g_checksum_update(sum, (const guint8 *) &n, sizeof(n));
-}
-
-static void
-hash_in6addr(GChecksum *sum, const struct in6_addr *a)
-{
- if (a)
- g_checksum_update(sum, (const guint8 *) a, sizeof(*a));
- else
- g_checksum_update(sum, (const guint8 *) &in6addr_any, sizeof(in6addr_any));
-}
-
-void
-nm_ip6_config_hash(const NMIP6Config *self, GChecksum *sum, gboolean dns_only)
-{
- guint32 i;
- const char * s;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *address;
- const NMPlatformIP6Route * route;
-
- g_return_if_fail(self);
- g_return_if_fail(sum);
-
- if (dns_only == FALSE) {
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, self, &address) {
- hash_in6addr(sum, &address->address);
- hash_u32(sum, address->plen);
- }
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, &route) {
- hash_in6addr(sum, &route->network);
- hash_u32(sum, route->plen);
- hash_in6addr(sum, &route->gateway);
- hash_u32(sum, route->metric);
- }
- }
-
- for (i = 0; i < nm_ip6_config_get_num_nameservers(self); i++)
- hash_in6addr(sum, nm_ip6_config_get_nameserver(self, i));
-
- for (i = 0; i < nm_ip6_config_get_num_domains(self); i++) {
- s = nm_ip6_config_get_domain(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip6_config_get_num_searches(self); i++) {
- s = nm_ip6_config_get_search(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip6_config_get_num_dns_options(self); i++) {
- s = nm_ip6_config_get_dns_option(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-}
-
-/**
- * nm_ip6_config_equal:
- * @a: first config to compare
- * @b: second config to compare
- *
- * Compares two #NMIP6Configs for basic equality. This means that all
- * attributes must exist in the same order in both configs (addresses, routes,
- * domains, DNS servers, etc) but some attributes (address lifetimes, and address
- * and route sources) are ignored.
- *
- * Returns: %TRUE if the configurations are basically equal to each other,
- * %FALSE if not
- */
-gboolean
-nm_ip6_config_equal(const NMIP6Config *a, const NMIP6Config *b)
-{
- nm_auto_free_checksum GChecksum *a_checksum = g_checksum_new(G_CHECKSUM_SHA1);
- nm_auto_free_checksum GChecksum *b_checksum = g_checksum_new(G_CHECKSUM_SHA1);
- guint8 a_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
- guint8 b_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
-
- if (a)
- nm_ip6_config_hash(a, a_checksum, FALSE);
- if (b)
- nm_ip6_config_hash(b, b_checksum, FALSE);
-
- nm_utils_checksum_get_digest(a_checksum, a_data);
- nm_utils_checksum_get_digest(b_checksum, b_data);
- return !memcmp(a_data, b_data, sizeof(a_data));
-}
-
-/*****************************************************************************/
-
-static void
-nameservers_to_gvalue(GArray *array, GValue *value)
-{
- GVariantBuilder builder;
- guint i = 0;
-
- g_variant_builder_init(&builder, G_VARIANT_TYPE("aay"));
-
- while (array && (i < array->len)) {
- struct in6_addr *addr;
-
- addr = &g_array_index(array, struct in6_addr, i++);
- g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(addr));
- }
-
- g_value_take_variant(value, g_variant_builder_end(&builder));
-}
-
-static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
- NMIP6Config * self = NM_IP6_CONFIG(object);
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- switch (prop_id) {
- case PROP_IFINDEX:
- g_value_set_int(value, priv->ifindex);
- break;
- case PROP_ADDRESS_DATA:
- case PROP_ADDRESSES:
- nm_assert(!!priv->address_data_variant == !!priv->addresses_variant);
-
- if (!priv->address_data_variant) {
- nm_utils_ip_addresses_to_dbus(AF_INET6,
- nm_ip6_config_lookup_addresses(self),
- priv->best_default_route,
- priv->privacy,
- &priv->address_data_variant,
- &priv->addresses_variant);
- g_variant_ref_sink(priv->address_data_variant);
- g_variant_ref_sink(priv->addresses_variant);
- }
- g_value_set_variant(value,
- prop_id == PROP_ADDRESS_DATA ? priv->address_data_variant
- : priv->addresses_variant);
- break;
-
- case PROP_ROUTE_DATA:
- case PROP_ROUTES:
- nm_assert(!!priv->route_data_variant == !!priv->routes_variant);
-
- if (!priv->route_data_variant) {
- nm_utils_ip_routes_to_dbus(AF_INET6,
- nm_ip6_config_lookup_routes(self),
- &priv->route_data_variant,
- &priv->routes_variant);
- g_variant_ref_sink(priv->route_data_variant);
- g_variant_ref_sink(priv->routes_variant);
- }
-
- g_value_set_variant(value,
- prop_id == PROP_ROUTE_DATA ? priv->route_data_variant
- : priv->routes_variant);
- break;
- case PROP_GATEWAY:
- if (priv->best_default_route) {
- g_value_take_string(value,
- nm_utils_inet6_ntop_dup(
- &NMP_OBJECT_CAST_IP6_ROUTE(priv->best_default_route)->gateway));
- } else
- g_value_set_string(value, NULL);
- break;
- case PROP_NAMESERVERS:
- nameservers_to_gvalue(priv->nameservers, value);
- break;
- case PROP_DOMAINS:
- nm_utils_g_value_set_strv(value, priv->domains);
- break;
- case PROP_SEARCHES:
- nm_utils_g_value_set_strv(value, priv->searches);
- break;
- case PROP_DNS_OPTIONS:
- nm_utils_g_value_set_strv(value, priv->dns_options);
- break;
- case PROP_DNS_PRIORITY:
- g_value_set_int(value, priv->dns_priority);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-static void
-set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
- NMIP6Config * self = NM_IP6_CONFIG(object);
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- switch (prop_id) {
- case PROP_MULTI_IDX:
- /* construct-only */
- priv->multi_idx = g_value_get_pointer(value);
- if (!priv->multi_idx)
- g_return_if_reached();
- nm_dedup_multi_index_ref(priv->multi_idx);
- break;
- case PROP_IFINDEX:
- /* construct-only */
- priv->ifindex = g_value_get_int(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-/*****************************************************************************/
-
-static void
-nm_ip6_config_init(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip6_addresses,
- NMP_OBJECT_TYPE_IP6_ADDRESS);
- nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip6_routes,
- NMP_OBJECT_TYPE_IP6_ROUTE);
-
- priv->nameservers = g_array_new(FALSE, TRUE, sizeof(struct in6_addr));
- priv->domains = g_ptr_array_new_with_free_func(g_free);
- priv->searches = g_ptr_array_new_with_free_func(g_free);
- priv->dns_options = g_ptr_array_new_with_free_func(g_free);
-}
-
-NMIP6Config *
-nm_ip6_config_new(NMDedupMultiIndex *multi_idx, int ifindex)
-{
- g_return_val_if_fail(ifindex >= -1, NULL);
- return g_object_new(NM_TYPE_IP6_CONFIG,
- NM_IP6_CONFIG_MULTI_IDX,
- multi_idx,
- NM_IP6_CONFIG_IFINDEX,
- ifindex,
- NULL);
-}
-
-NMIP6Config *
-nm_ip6_config_new_cloned(const NMIP6Config *src)
-{
- NMIP6Config *new;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(src), NULL);
-
- new = nm_ip6_config_new(nm_ip6_config_get_multi_idx(src), nm_ip6_config_get_ifindex(src));
- nm_ip6_config_replace(new, src, NULL);
- return new;
-}
-
-static void
-finalize(GObject *object)
-{
- NMIP6Config * self = NM_IP6_CONFIG(object);
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nm_clear_nmp_object(&priv->best_default_route);
-
- nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip6_addresses);
- nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip6_routes);
-
- nm_clear_g_variant(&priv->address_data_variant);
- nm_clear_g_variant(&priv->addresses_variant);
- nm_clear_g_variant(&priv->route_data_variant);
- nm_clear_g_variant(&priv->routes_variant);
-
- g_array_unref(priv->nameservers);
- g_ptr_array_unref(priv->domains);
- g_ptr_array_unref(priv->searches);
- g_ptr_array_unref(priv->dns_options);
-
- G_OBJECT_CLASS(nm_ip6_config_parent_class)->finalize(object);
-
- nm_dedup_multi_index_unref(priv->multi_idx);
-}
-
-static const NMDBusInterfaceInfoExtended interface_info_ip6_config = {
- .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
- NM_DBUS_INTERFACE_IP6_CONFIG,
- .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses",
- "a(ayuay)",
- NM_IP6_CONFIG_ADDRESSES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
- "aa{sv}",
- NM_IP6_CONFIG_ADDRESS_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP6_CONFIG_GATEWAY),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes",
- "a(ayuayu)",
- NM_IP6_CONFIG_ROUTES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData",
- "aa{sv}",
- NM_IP6_CONFIG_ROUTE_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers",
- "aay",
- NM_IP6_CONFIG_NAMESERVERS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP6_CONFIG_DOMAINS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches",
- "as",
- NM_IP6_CONFIG_SEARCHES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions",
- "as",
- NM_IP6_CONFIG_DNS_OPTIONS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority",
- "i",
- NM_IP6_CONFIG_DNS_PRIORITY), ), ),
-};
-
-static void
-nm_ip6_config_class_init(NMIP6ConfigClass *klass)
-{
- GObjectClass * object_class = G_OBJECT_CLASS(klass);
- NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
- NMIPConfigClass * ip_config_class = NM_IP_CONFIG_CLASS(klass);
-
- ip_config_class->is_ipv4 = FALSE;
- ip_config_class->addr_family = AF_INET6;
-
- dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/IP6Config");
- dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_ip6_config);
-
- object_class->get_property = get_property;
- object_class->set_property = set_property;
- object_class->finalize = finalize;
-
- obj_properties[PROP_MULTI_IDX] =
- g_param_spec_pointer(NM_IP6_CONFIG_MULTI_IDX,
- "",
- "",
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IFINDEX] =
- g_param_spec_int(NM_IP6_CONFIG_IFINDEX,
- "",
- "",
- -1,
- G_MAXINT,
- -1,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDRESS_DATA] =
- g_param_spec_variant(NM_IP6_CONFIG_ADDRESS_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDRESSES] =
- g_param_spec_variant(NM_IP6_CONFIG_ADDRESSES,
- "",
- "",
- G_VARIANT_TYPE("a(ayuay)"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTE_DATA] =
- g_param_spec_variant(NM_IP6_CONFIG_ROUTE_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTES] = g_param_spec_variant(NM_IP6_CONFIG_ROUTES,
- "",
- "",
- G_VARIANT_TYPE("a(ayuayu)"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_GATEWAY] = g_param_spec_string(NM_IP6_CONFIG_GATEWAY,
- "",
- "",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_NAMESERVERS] =
- g_param_spec_variant(NM_IP6_CONFIG_NAMESERVERS,
- "",
- "",
- G_VARIANT_TYPE("aay"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DOMAINS] = g_param_spec_boxed(NM_IP6_CONFIG_DOMAINS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_SEARCHES] = g_param_spec_boxed(NM_IP6_CONFIG_SEARCHES,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DNS_OPTIONS] =
- g_param_spec_boxed(NM_IP6_CONFIG_DNS_OPTIONS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DNS_PRIORITY] = g_param_spec_int(NM_IP6_CONFIG_DNS_PRIORITY,
- "",
- "",
- G_MININT32,
- G_MAXINT32,
- 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-}
diff --git a/src/core/nm-ip6-config.h b/src/core/nm-ip6-config.h
deleted file mode 100644
index a54040fc59..0000000000
--- a/src/core/nm-ip6-config.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2008 - 2013 Red Hat, Inc.
- */
-
-#ifndef __NETWORKMANAGER_IP6_CONFIG_H__
-#define __NETWORKMANAGER_IP6_CONFIG_H__
-
-#include <netinet/in.h>
-
-#include "nm-setting-ip6-config.h"
-
-#include "libnm-glib-aux/nm-dedup-multi.h"
-#include "libnm-platform/nmp-object.h"
-#include "nm-ip-config.h"
-
-/*****************************************************************************/
-
-void nm_ip_config_iter_ip6_address_init(NMDedupMultiIter *iter, const NMIP6Config *self);
-void nm_ip_config_iter_ip6_route_init(NMDedupMultiIter *iter, const NMIP6Config *self);
-
-#define nm_ip_config_iter_ip6_address_for_each(iter, self, address) \
- for (nm_ip_config_iter_ip6_address_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip6_address((iter), (address));)
-
-#define nm_ip_config_iter_ip6_route_for_each(iter, self, route) \
- for (nm_ip_config_iter_ip6_route_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip6_route((iter), (route));)
-
-/*****************************************************************************/
-
-#define NM_TYPE_IP6_CONFIG (nm_ip6_config_get_type())
-#define NM_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IP6_CONFIG, NMIP6Config))
-#define NM_IP6_CONFIG_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
-#define NM_IS_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_IP6_CONFIG))
-#define NM_IS_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_IP6_CONFIG))
-#define NM_IP6_CONFIG_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
-
-typedef struct _NMIP6ConfigClass NMIP6ConfigClass;
-
-/* internal */
-#define NM_IP6_CONFIG_MULTI_IDX "multi-idx"
-#define NM_IP6_CONFIG_IFINDEX "ifindex"
-
-/* public */
-#define NM_IP6_CONFIG_ADDRESS_DATA "address-data"
-#define NM_IP6_CONFIG_ROUTE_DATA "route-data"
-#define NM_IP6_CONFIG_GATEWAY "gateway"
-#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
-#define NM_IP6_CONFIG_DOMAINS "domains"
-#define NM_IP6_CONFIG_SEARCHES "searches"
-#define NM_IP6_CONFIG_DNS_OPTIONS "dns-options"
-#define NM_IP6_CONFIG_DNS_PRIORITY "dns-priority"
-
-/* deprecated */
-#define NM_IP6_CONFIG_ADDRESSES "addresses"
-#define NM_IP6_CONFIG_ROUTES "routes"
-
-GType nm_ip6_config_get_type(void);
-
-NMIP6Config *nm_ip6_config_new(struct _NMDedupMultiIndex *multi_idx, int ifindex);
-NMIP6Config *nm_ip6_config_new_cloned(const NMIP6Config *src);
-
-NMIP6Config *nm_ip6_config_clone(const NMIP6Config *self);
-int nm_ip6_config_get_ifindex(const NMIP6Config *self);
-
-struct _NMDedupMultiIndex *nm_ip6_config_get_multi_idx(const NMIP6Config *self);
-
-NMIP6Config *nm_ip6_config_capture(struct _NMDedupMultiIndex *multi_idx,
- NMPlatform * platform,
- int ifindex,
- NMSettingIP6ConfigPrivacy use_temporary);
-
-void nm_ip6_config_add_dependent_routes(NMIP6Config *self,
- guint32 route_table,
- guint32 route_metric,
- gboolean is_vrf);
-
-gboolean nm_ip6_config_commit(const NMIP6Config * self,
- NMPlatform * platform,
- NMIPRouteTableSyncMode route_table_sync,
- GPtrArray ** out_temporary_not_available);
-void nm_ip6_config_merge_setting(NMIP6Config * self,
- NMSettingIPConfig *setting,
- guint32 route_table,
- guint32 route_metric);
-NMSetting *nm_ip6_config_create_setting(const NMIP6Config *self, gboolean maybe_ipv6_disabled);
-
-void nm_ip6_config_merge(NMIP6Config * dst,
- const NMIP6Config * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty);
-void nm_ip6_config_subtract(NMIP6Config * dst,
- const NMIP6Config *src,
- guint32 default_route_metric_penalty);
-void nm_ip6_config_intersect(NMIP6Config * dst,
- const NMIP6Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty);
-NMIP6Config *nm_ip6_config_intersect_alloc(const NMIP6Config *a,
- const NMIP6Config *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty);
-gboolean
-nm_ip6_config_replace(NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes);
-
-const NMPObject *nm_ip6_config_best_default_route_get(const NMIP6Config *self);
-const NMPObject *_nm_ip6_config_best_default_route_find(const NMIP6Config *self);
-
-enum _NMIPConfigFlags;
-
-void nm_ip6_config_set_config_flags(NMIP6Config * self,
- enum _NMIPConfigFlags flags,
- enum _NMIPConfigFlags mask);
-enum _NMIPConfigFlags nm_ip6_config_get_config_flags(const NMIP6Config *self);
-
-const NMDedupMultiHeadEntry *nm_ip6_config_lookup_addresses(const NMIP6Config *self);
-void nm_ip6_config_reset_addresses(NMIP6Config *self);
-void nm_ip6_config_add_address(NMIP6Config *self, const NMPlatformIP6Address *address);
-void _nmtst_ip6_config_del_address(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_addresses(const NMIP6Config *self);
-const NMPlatformIP6Address *nm_ip6_config_get_first_address(const NMIP6Config *self);
-const NMPlatformIP6Address *_nmtst_ip6_config_get_address(const NMIP6Config *self, guint i);
-gboolean nm_ip6_config_address_exists(const NMIP6Config *self, const NMPlatformIP6Address *address);
-const NMPlatformIP6Address *nm_ip6_config_lookup_address(const NMIP6Config * self,
- const struct in6_addr *addr);
-gboolean _nmtst_ip6_config_addresses_sort(NMIP6Config *self);
-gboolean nm_ip6_config_has_any_dad_pending(const NMIP6Config *self, const NMIP6Config *candidates);
-
-const NMDedupMultiHeadEntry *nm_ip6_config_lookup_routes(const NMIP6Config *self);
-void nm_ip6_config_reset_routes(NMIP6Config *self);
-void nm_ip6_config_add_route(NMIP6Config * self,
- const NMPlatformIP6Route *route,
- const NMPObject ** out_obj_new);
-void _nmtst_ip6_config_del_route(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_routes(const NMIP6Config *self);
-const NMPlatformIP6Route * _nmtst_ip6_config_get_route(const NMIP6Config *self, guint i);
-
-const NMPlatformIP6Route * nm_ip6_config_get_direct_route_for_host(const NMIP6Config * self,
- const struct in6_addr *host,
- guint32 route_table);
-const NMPlatformIP6Address *nm_ip6_config_get_subnet_for_host(const NMIP6Config * self,
- const struct in6_addr *host);
-
-void nm_ip6_config_reset_nameservers(NMIP6Config *self);
-void nm_ip6_config_add_nameserver(NMIP6Config *self, const struct in6_addr *nameserver);
-void nm_ip6_config_del_nameserver(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_nameservers(const NMIP6Config *self);
-const struct in6_addr *nm_ip6_config_get_nameserver(const NMIP6Config *self, guint i);
-
-void nm_ip6_config_reset_domains(NMIP6Config *self);
-void nm_ip6_config_add_domain(NMIP6Config *self, const char *domain);
-void nm_ip6_config_del_domain(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_domains(const NMIP6Config *self);
-const char *nm_ip6_config_get_domain(const NMIP6Config *self, guint i);
-
-void nm_ip6_config_reset_searches(NMIP6Config *self);
-void nm_ip6_config_add_search(NMIP6Config *self, const char *search);
-void nm_ip6_config_del_search(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_searches(const NMIP6Config *self);
-const char *nm_ip6_config_get_search(const NMIP6Config *self, guint i);
-
-void nm_ip6_config_reset_dns_options(NMIP6Config *self);
-void nm_ip6_config_add_dns_option(NMIP6Config *self, const char *option);
-void nm_ip6_config_del_dns_option(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_dns_options(const NMIP6Config *self);
-const char *nm_ip6_config_get_dns_option(const NMIP6Config *self, guint i);
-
-void nm_ip6_config_set_dns_priority(NMIP6Config *self, int priority);
-int nm_ip6_config_get_dns_priority(const NMIP6Config *self);
-
-void nm_ip6_config_set_never_default(NMIP6Config *self, gboolean never_default);
-gboolean nm_ip6_config_get_never_default(const NMIP6Config *self);
-
-const NMPObject *nm_ip6_config_nmpobj_lookup(const NMIP6Config *self, const NMPObject *needle);
-gboolean nm_ip6_config_nmpobj_remove(NMIP6Config *self, const NMPObject *needle);
-
-void nm_ip6_config_hash(const NMIP6Config *self, GChecksum *sum, gboolean dns_only);
-gboolean nm_ip6_config_equal(const NMIP6Config *a, const NMIP6Config *b);
-
-void nm_ip6_config_set_privacy(NMIP6Config *self, NMSettingIP6ConfigPrivacy privacy);
-
-struct _NMNDiscAddress;
-void nm_ip6_config_reset_addresses_ndisc(NMIP6Config * self,
- const struct _NMNDiscAddress *addresses,
- guint addresses_n,
- guint8 plen,
- guint32 ifa_flags);
-struct _NMNDiscRoute;
-struct _NMNDiscGateway;
-void nm_ip6_config_reset_routes_ndisc(NMIP6Config * self,
- const struct _NMNDiscGateway *gateways,
- guint gateways_n,
- const struct _NMNDiscRoute * routes,
- guint routes_n,
- guint32 route_table,
- guint32 route_metric);
-
-void nm_ip6_config_update_routes_metric(NMIP6Config *self, gint64 metric);
-
-#endif /* __NETWORKMANAGER_IP6_CONFIG_H__ */
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index 49c56bf68f..569229ca0a 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -2276,13 +2276,7 @@ system_unmanaged_devices_changed_cb(NMSettings *settings, GParamSpec *pspec, gpo
static void
hostname_changed_cb(NMHostnameManager *hostname_manager, GParamSpec *pspec, NMManager *self)
{
- NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
- const char * hostname;
-
- hostname = nm_hostname_manager_get_hostname(priv->hostname_manager);
-
nm_dispatcher_call_hostname(NULL, NULL, NULL);
- nm_dhcp_manager_set_default_hostname(nm_dhcp_manager_get(), hostname);
}
/*****************************************************************************/
@@ -2599,8 +2593,6 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat
if (out_generated)
*out_generated = FALSE;
- nm_device_capture_initial_config(device);
-
if (!nm_device_can_assume_connections(device)) {
nm_device_assume_state_reset(device);
_LOG2D(LOGD_DEVICE, device, "assume: device cannot assume connection");
diff --git a/src/core/nm-pacrunner-manager.c b/src/core/nm-pacrunner-manager.c
index 67930dbae0..6eca4d9432 100644
--- a/src/core/nm-pacrunner-manager.c
+++ b/src/core/nm-pacrunner-manager.c
@@ -7,15 +7,14 @@
#include "nm-pacrunner-manager.h"
-#include "nm-utils.h"
-#include "NetworkManagerUtils.h"
-#include "libnm-platform/nm-platform.h"
-#include "nm-dbus-manager.h"
-#include "nm-proxy-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "c-list/src/c-list.h"
#include "libnm-glib-aux/nm-dbus-aux.h"
+#include "libnm-platform/nm-platform.h"
+
+#include "NetworkManagerUtils.h"
+#include "nm-dbus-manager.h"
+#include "nm-l3-config-data.h"
+#include "nm-utils.h"
#define PACRUNNER_DBUS_SERVICE "org.pacrunner"
#define PACRUNNER_DBUS_INTERFACE "org.pacrunner.Manager"
@@ -124,58 +123,48 @@ NM_AUTO_DEFINE_FCN0(NMPacrunnerConfId *, _nm_auto_unref_conf_id, conf_id_unref);
/*****************************************************************************/
static void
-get_ip_domains(GPtrArray *domains, NMIPConfig *ip_config)
+get_ip_domains(GPtrArray *domains, const NML3ConfigData *l3cd, int addr_family)
{
NMDedupMultiIter ipconf_iter;
char * cidr;
- guint i, num;
+ guint num;
+ guint i;
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
- int addr_family;
const NMPlatformIPAddress *address;
- const NMPlatformIPRoute * routes;
-
- if (!ip_config)
- return;
-
- addr_family = nm_ip_config_get_addr_family(ip_config);
+ const NMPlatformIPRoute * route;
+ const char *const * strv;
- num = nm_ip_config_get_num_searches(ip_config);
+ strv = nm_l3_config_data_get_searches(l3cd, addr_family, &num);
for (i = 0; i < num; i++)
- g_ptr_array_add(domains, g_strdup(nm_ip_config_get_search(ip_config, i)));
+ g_ptr_array_add(domains, g_strdup(strv[i]));
- num = nm_ip_config_get_num_domains(ip_config);
+ strv = nm_l3_config_data_get_domains(l3cd, addr_family, &num);
for (i = 0; i < num; i++)
- g_ptr_array_add(domains, g_strdup(nm_ip_config_get_domain(ip_config, i)));
+ g_ptr_array_add(domains, g_strdup(strv[i]));
- nm_ip_config_iter_ip_address_for_each (&ipconf_iter, ip_config, &address) {
+ nm_l3_config_data_iter_ip_address_for_each (&ipconf_iter, l3cd, addr_family, &address) {
cidr = g_strdup_printf("%s/%u",
nm_utils_inet_ntop(addr_family, address->address_ptr, sbuf),
address->plen);
g_ptr_array_add(domains, cidr);
}
- nm_ip_config_iter_ip_route_for_each (&ipconf_iter, ip_config, &routes) {
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(routes))
+ nm_l3_config_data_iter_ip_route_for_each (&ipconf_iter, l3cd, addr_family, &route) {
+ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
continue;
cidr = g_strdup_printf("%s/%u",
- nm_utils_inet_ntop(addr_family, routes->network_ptr, sbuf),
- routes->plen);
+ nm_utils_inet_ntop(addr_family, route->network_ptr, sbuf),
+ route->plen);
g_ptr_array_add(domains, cidr);
}
}
static GVariant *
-_make_request_create_proxy_configuration(NMProxyConfig *proxy_config,
- const char * iface,
- NMIP4Config * ip4_config,
- NMIP6Config * ip6_config)
+_make_request_create_proxy_configuration(const char *iface, const NML3ConfigData *l3cd)
{
GVariantBuilder builder;
NMProxyConfigMethod method;
- const char * pac_url;
- const char * pac_script;
-
- nm_assert(NM_IS_PROXY_CONFIG(proxy_config));
+ const char * s;
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
@@ -183,20 +172,19 @@ _make_request_create_proxy_configuration(NMProxyConfig *proxy_config,
g_variant_builder_add(&builder, "{sv}", "Interface", g_variant_new_string(iface));
}
- method = nm_proxy_config_get_method(proxy_config);
+ method = l3cd ? nm_l3_config_data_get_proxy_method(l3cd) : NM_PROXY_CONFIG_METHOD_UNKNOWN;
+
switch (method) {
case NM_PROXY_CONFIG_METHOD_AUTO:
g_variant_builder_add(&builder, "{sv}", "Method", g_variant_new_string("auto"));
- pac_url = nm_proxy_config_get_pac_url(proxy_config);
- if (pac_url) {
- g_variant_builder_add(&builder, "{sv}", "URL", g_variant_new_string(pac_url));
- }
+ s = nm_l3_config_data_get_proxy_pac_url(l3cd);
+ if (s)
+ g_variant_builder_add(&builder, "{sv}", "URL", g_variant_new_string(s));
- pac_script = nm_proxy_config_get_pac_script(proxy_config);
- if (pac_script) {
- g_variant_builder_add(&builder, "{sv}", "Script", g_variant_new_string(pac_script));
- }
+ s = nm_l3_config_data_get_proxy_pac_script(l3cd);
+ if (s)
+ g_variant_builder_add(&builder, "{sv}", "Script", g_variant_new_string(s));
break;
case NM_PROXY_CONFIG_METHOD_UNKNOWN:
case NM_PROXY_CONFIG_METHOD_NONE:
@@ -204,18 +192,19 @@ _make_request_create_proxy_configuration(NMProxyConfig *proxy_config,
break;
}
- g_variant_builder_add(&builder,
- "{sv}",
- "BrowserOnly",
- g_variant_new_boolean(nm_proxy_config_get_browser_only(proxy_config)));
+ g_variant_builder_add(
+ &builder,
+ "{sv}",
+ "BrowserOnly",
+ g_variant_new_boolean(l3cd ? !!nm_l3_config_data_get_proxy_browser_only(l3cd) : FALSE));
- if (ip4_config || ip6_config) {
+ if (l3cd) {
gs_unref_ptrarray GPtrArray *domains = NULL;
domains = g_ptr_array_new_with_free_func(g_free);
- get_ip_domains(domains, NM_IP_CONFIG_CAST(ip4_config));
- get_ip_domains(domains, NM_IP_CONFIG_CAST(ip6_config));
+ get_ip_domains(domains, l3cd, AF_INET);
+ get_ip_domains(domains, l3cd, AF_INET6);
if (domains->len > 0) {
g_variant_builder_add(
@@ -356,10 +345,8 @@ _try_start_service_by_name(NMPacrunnerManager *self)
/**
* nm_pacrunner_manager_add:
* @self: the #NMPacrunnerManager
- * @proxy_config: proxy config of the connection
* @iface: the iface for the connection or %NULL
- * @ip4_config: IP4 config of the connection to extract domain info from
- * @ip6_config: IP6 config of the connection to extract domain info from
+ * @l3cd: the #NML3ConfigData of the connection to extract domain info from
*
* Returns: a #NMPacrunnerConfId id. The function cannot
* fail and always returns a non NULL pointer. The conf-id may
@@ -367,18 +354,13 @@ _try_start_service_by_name(NMPacrunnerManager *self)
* Note that the conf-id keeps the @self instance alive.
*/
NMPacrunnerConfId *
-nm_pacrunner_manager_add(NMPacrunnerManager *self,
- NMProxyConfig * proxy_config,
- const char * iface,
- NMIP4Config * ip4_config,
- NMIP6Config * ip6_config)
+nm_pacrunner_manager_add(NMPacrunnerManager *self, const char *iface, const NML3ConfigData *l3cd)
{
NMPacrunnerManagerPrivate *priv;
NMPacrunnerConfId * conf_id;
gs_free char * log_msg = NULL;
g_return_val_if_fail(NM_IS_PACRUNNER_MANAGER(self), NULL);
- g_return_val_if_fail(proxy_config, NULL);
priv = NM_PACRUNNER_MANAGER_GET_PRIVATE(self);
@@ -387,8 +369,7 @@ nm_pacrunner_manager_add(NMPacrunnerManager *self,
.log_id = ++priv->log_id_counter,
.refcount = 1,
.self = g_object_ref(self),
- .parameters = g_variant_ref_sink(
- _make_request_create_proxy_configuration(proxy_config, iface, ip4_config, ip6_config)),
+ .parameters = g_variant_ref_sink(_make_request_create_proxy_configuration(iface, l3cd)),
};
c_list_link_tail(&priv->conf_id_lst_head, &conf_id->conf_id_lst);
diff --git a/src/core/nm-pacrunner-manager.h b/src/core/nm-pacrunner-manager.h
index fd40f1204d..3f16908f4e 100644
--- a/src/core/nm-pacrunner-manager.h
+++ b/src/core/nm-pacrunner-manager.h
@@ -26,11 +26,8 @@ GType nm_pacrunner_manager_get_type(void);
NMPacrunnerManager *nm_pacrunner_manager_get(void);
-NMPacrunnerConfId *nm_pacrunner_manager_add(NMPacrunnerManager *self,
- NMProxyConfig * proxy_config,
- const char * iface,
- NMIP4Config * ip4_config,
- NMIP6Config * ip6_config);
+NMPacrunnerConfId *
+nm_pacrunner_manager_add(NMPacrunnerManager *self, const char *iface, const NML3ConfigData *l3cd);
void nm_pacrunner_manager_remove(NMPacrunnerConfId *conf_id);
diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c
index e85863611a..610422383d 100644
--- a/src/core/nm-policy.c
+++ b/src/core/nm-policy.c
@@ -11,28 +11,31 @@
#include <unistd.h>
#include <netdb.h>
+#include "libnm-core-intern/nm-core-internal.h"
+#include "libnm-platform/nm-platform.h"
+#include "libnm-platform/nmp-object.h"
+
#include "NetworkManagerUtils.h"
-#include "nm-act-request.h"
-#include "nm-keep-alive.h"
#include "devices/nm-device.h"
-#include "nm-setting-ip4-config.h"
-#include "nm-setting-connection.h"
-#include "libnm-platform/nm-platform.h"
#include "dns/nm-dns-manager.h"
-#include "vpn/nm-vpn-manager.h"
+#include "nm-act-request.h"
#include "nm-auth-utils.h"
-#include "nm-firewalld-manager.h"
+#include "nm-config.h"
+#include "nm-dhcp-config.h"
#include "nm-dispatcher.h"
-#include "nm-utils.h"
-#include "libnm-core-intern/nm-core-internal.h"
+#include "nm-firewalld-manager.h"
+#include "nm-hostname-manager.h"
+#include "nm-keep-alive.h"
+#include "nm-l3-config-data.h"
#include "nm-manager.h"
-#include "settings/nm-settings.h"
-#include "settings/nm-settings-connection.h"
-#include "settings/nm-agent-manager.h"
-#include "nm-dhcp-config.h"
-#include "nm-config.h"
#include "nm-netns.h"
-#include "nm-hostname-manager.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-utils.h"
+#include "settings/nm-agent-manager.h"
+#include "settings/nm-settings-connection.h"
+#include "settings/nm-settings.h"
+#include "vpn/nm-vpn-manager.h"
/*****************************************************************************/
@@ -136,30 +139,6 @@ static NMDevice *get_default_device(NMPolicy *self, int addr_family);
/*****************************************************************************/
-static void
-_dns_manager_set_ip_config(NMDnsManager * dns_manager,
- NMIPConfig * ip_config,
- NMDnsIPConfigType ip_config_type,
- NMDevice * device)
-{
- if (device && nm_device_sys_iface_state_is_external(device)) {
- nm_dns_manager_set_ip_config(dns_manager, ip_config, NM_DNS_IP_CONFIG_TYPE_REMOVED);
- return;
- }
-
- if (NM_IN_SET(ip_config_type, NM_DNS_IP_CONFIG_TYPE_DEFAULT, NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE)
- && device
- && nm_device_get_route_metric_default(nm_device_get_device_type(device))
- == NM_VPN_ROUTE_METRIC_DEFAULT) {
- /* some device types are inherently VPN. */
- ip_config_type = NM_DNS_IP_CONFIG_TYPE_VPN;
- }
-
- nm_dns_manager_set_ip_config(dns_manager, ip_config, ip_config_type);
-}
-
-/*****************************************************************************/
-
typedef struct {
NMPlatformIP6Address prefix;
NMDevice * device; /* The requesting ("uplink") device */
@@ -974,7 +953,7 @@ update_default_ac(NMPolicy *self, int addr_family, NMActiveConnection *best)
nm_active_connection_set_default(best, addr_family, TRUE);
}
-static gpointer
+static const NML3ConfigData *
get_best_ip_config(NMPolicy * self,
int addr_family,
const char ** out_ip_iface,
@@ -982,20 +961,21 @@ get_best_ip_config(NMPolicy * self,
NMDevice ** out_device,
NMVpnConnection ** out_vpn)
{
- NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self);
- gpointer conf, best_conf = NULL;
- const CList * tmp_list;
- NMActiveConnection *ac;
- guint64 best_metric = G_MAXUINT64;
- NMVpnConnection * best_vpn = NULL;
+ NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self);
+ const NML3ConfigData *l3cd_best = NULL;
+ const CList * tmp_list;
+ NMActiveConnection * ac;
+ guint64 best_metric = G_MAXUINT64;
+ NMVpnConnection * best_vpn = NULL;
nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
- NMVpnConnection * candidate;
- NMVpnConnectionState vpn_state;
- const NMPObject * obj;
- guint32 metric;
+ const NML3ConfigData *l3cd;
+ NMVpnConnection * candidate;
+ NMVpnConnectionState vpn_state;
+ const NMPObject * obj;
+ guint32 metric;
if (!NM_IS_VPN_CONNECTION(ac))
continue;
@@ -1006,24 +986,18 @@ get_best_ip_config(NMPolicy * self,
if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED)
continue;
- if (addr_family == AF_INET)
- conf = nm_vpn_connection_get_ip4_config(candidate);
- else
- conf = nm_vpn_connection_get_ip6_config(candidate);
- if (!conf)
+ l3cd = nm_vpn_connection_get_l3cd(candidate, addr_family);
+ if (!l3cd)
continue;
- if (addr_family == AF_INET)
- obj = nm_ip4_config_best_default_route_get(conf);
- else
- obj = nm_ip6_config_best_default_route_get(conf);
+ obj = nm_l3_config_data_get_best_default_route(l3cd, addr_family);
if (!obj)
continue;
metric = NMP_OBJECT_CAST_IPX_ROUTE(obj)->rx.metric;
if (metric <= best_metric) {
best_metric = metric;
- best_conf = conf;
+ l3cd_best = l3cd;
best_vpn = candidate;
}
}
@@ -1033,25 +1007,20 @@ get_best_ip_config(NMPolicy * self,
NM_SET_OUT(out_vpn, best_vpn);
NM_SET_OUT(out_ac, NM_ACTIVE_CONNECTION(best_vpn));
NM_SET_OUT(out_ip_iface, nm_vpn_connection_get_ip_iface(best_vpn, TRUE));
- return best_conf;
+ return l3cd_best;
}
ac = get_best_active_connection(self, addr_family, TRUE);
if (ac) {
NMDevice *device = nm_active_connection_get_device(ac);
- nm_assert(device);
-
- if (addr_family == AF_INET)
- conf = nm_device_get_ip4_config(device);
- else
- conf = nm_device_get_ip6_config(device);
+ nm_assert(NM_IS_DEVICE(device));
NM_SET_OUT(out_device, device);
NM_SET_OUT(out_vpn, NULL);
NM_SET_OUT(out_ac, ac);
NM_SET_OUT(out_ip_iface, nm_device_get_ip_iface(device));
- return conf;
+ return nm_device_get_l3cd(device, TRUE);
}
NM_SET_OUT(out_device, NULL);
@@ -1069,8 +1038,6 @@ update_ip4_routing(NMPolicy *self, gboolean force_update)
NMVpnConnection * vpn = NULL;
NMActiveConnection *best_ac = NULL;
const char * ip_iface = NULL;
- const CList * tmp_list;
- NMActiveConnection *ac;
/* Note that we might have an IPv4 VPN tunneled over an IPv6-only device,
* so we can get (vpn != NULL && best == NULL).
@@ -1088,9 +1055,11 @@ update_ip4_routing(NMPolicy *self, gboolean force_update)
return;
if (best) {
+ const CList * tmp_list;
+ NMActiveConnection *ac;
+
nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
- if (NM_IS_VPN_CONNECTION(ac) && nm_vpn_connection_get_ip4_config(NM_VPN_CONNECTION(ac))
- && !nm_active_connection_get_device(ac))
+ if (NM_IS_VPN_CONNECTION(ac) && !nm_active_connection_get_device(ac))
nm_active_connection_set_device(ac, best);
}
}
@@ -1132,8 +1101,6 @@ update_ip6_routing(NMPolicy *self, gboolean force_update)
NMVpnConnection * vpn = NULL;
NMActiveConnection *best_ac = NULL;
const char * ip_iface = NULL;
- NMActiveConnection *ac;
- const CList * tmp_list;
/* Note that we might have an IPv6 VPN tunneled over an IPv4-only device,
* so we can get (vpn != NULL && best == NULL).
@@ -1151,9 +1118,11 @@ update_ip6_routing(NMPolicy *self, gboolean force_update)
return;
if (best) {
+ const CList * tmp_list;
+ NMActiveConnection *ac;
+
nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
- if (NM_IS_VPN_CONNECTION(ac) && nm_vpn_connection_get_ip6_config(NM_VPN_CONNECTION(ac))
- && !nm_active_connection_get_device(ac))
+ if (NM_IS_VPN_CONNECTION(ac) && !nm_active_connection_get_device(ac))
nm_active_connection_set_device(ac, best);
}
}
@@ -1176,25 +1145,38 @@ update_ip6_routing(NMPolicy *self, gboolean force_update)
static void
update_ip_dns(NMPolicy *self, int addr_family, NMDevice *changed_device)
{
- NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
- gpointer ip_config;
- const char * ip_iface = NULL;
- NMVpnConnection *vpn = NULL;
- NMDevice * device = NULL;
+ NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self);
+ const NML3ConfigData *l3cd;
+ const char * ip_iface = NULL;
+ NMVpnConnection * vpn = NULL;
+ NMDevice * device = NULL;
nm_assert_addr_family(addr_family);
- ip_config = get_best_ip_config(self, addr_family, &ip_iface, NULL, &device, &vpn);
- if (ip_config) {
+ l3cd = get_best_ip_config(self, addr_family, &ip_iface, NULL, &device, &vpn);
+ if (l3cd) {
+ NMDnsIPConfigType ip_config_type;
+
+ nm_assert(!device || NM_IS_DEVICE(device));
+ nm_assert(!vpn || NM_IS_VPN_CONNECTION(vpn));
+ nm_assert((!!device) != (!!vpn));
+
/* Tell the DNS manager this config is preferred by re-adding it with
* a different IP config type.
*/
- _dns_manager_set_ip_config(NM_POLICY_GET_PRIVATE(self)->dns_manager,
- ip_config,
- (vpn || (device && nm_device_is_vpn(device)))
- ? NM_DNS_IP_CONFIG_TYPE_VPN
- : NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE,
- device);
+ if (device && nm_device_sys_iface_state_is_external(device))
+ ip_config_type = NM_DNS_IP_CONFIG_TYPE_REMOVED;
+ else if (vpn || (device && nm_device_is_vpn(device)))
+ ip_config_type = NM_DNS_IP_CONFIG_TYPE_VPN;
+ else
+ ip_config_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
+
+ nm_dns_manager_set_ip_config(NM_POLICY_GET_PRIVATE(self)->dns_manager,
+ addr_family,
+ ((gconstpointer) device) ?: ((gconstpointer) vpn),
+ l3cd,
+ ip_config_type,
+ TRUE);
}
if (addr_family == AF_INET6) {
@@ -1909,9 +1891,7 @@ device_state_changed(NMDevice * device,
NMPolicy * self = _PRIV_TO_SELF(priv);
NMActiveConnection * ac;
NMSettingsConnection *sett_conn = nm_device_get_settings_connection(device);
- NMIP4Config * ip4_config;
- NMIP6Config * ip6_config;
- NMSettingConnection * s_con = NULL;
+ NMSettingConnection * s_con = NULL;
switch (nm_device_state_reason_check(reason)) {
case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED:
@@ -2013,27 +1993,6 @@ device_state_changed(NMDevice * device,
/* Reset auto retries back to default since connection was successful */
nm_settings_connection_autoconnect_retries_reset(sett_conn);
}
-
- /* Add device's new IPv4 and IPv6 configs to DNS */
-
- nm_dns_manager_begin_updates(priv->dns_manager, __func__);
-
- ip4_config = nm_device_get_ip4_config(device);
- if (ip4_config)
- _dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip4_config),
- NM_DNS_IP_CONFIG_TYPE_DEFAULT,
- device);
- ip6_config = nm_device_get_ip6_config(device);
- if (ip6_config)
- _dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip6_config),
- NM_DNS_IP_CONFIG_TYPE_DEFAULT,
- device);
-
- update_routing_and_dns(self, FALSE, device);
-
- nm_dns_manager_end_updates(priv->dns_manager, __func__);
break;
case NM_DEVICE_STATE_UNMANAGED:
case NM_DEVICE_STATE_UNAVAILABLE:
@@ -2135,24 +2094,16 @@ device_state_changed(NMDevice * device,
}
static void
-device_ip_config_changed(NMDevice * device,
- NMIPConfig *new_config,
- NMIPConfig *old_config,
- gpointer user_data)
+device_l3cd_changed(NMDevice * device,
+ const NML3ConfigData *l3cd_old,
+ const NML3ConfigData *l3cd_new,
+ gpointer user_data)
{
NMPolicyPrivate *priv = user_data;
NMPolicy * self = _PRIV_TO_SELF(priv);
- int addr_family;
- nm_assert(new_config || old_config);
- nm_assert(!new_config || NM_IS_IP_CONFIG(new_config));
- nm_assert(!old_config || NM_IS_IP_CONFIG(old_config));
-
- if (new_config) {
- addr_family = nm_ip_config_get_addr_family(new_config);
- nm_assert(!old_config || addr_family == nm_ip_config_get_addr_family(old_config));
- } else
- addr_family = nm_ip_config_get_addr_family(old_config);
+ nm_assert(!l3cd_new || NM_IS_L3_CONFIG_DATA(l3cd_new));
+ nm_assert(!l3cd_old || NM_IS_L3_CONFIG_DATA(l3cd_old));
nm_dns_manager_begin_updates(priv->dns_manager, __func__);
@@ -2161,30 +2112,25 @@ device_ip_config_changed(NMDevice * device,
* ignore IP config changes but when the device is in activated state.
* Prevents unnecessary changes to DNS information.
*/
- if (nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) {
- if (old_config != new_config) {
- if (new_config)
- _dns_manager_set_ip_config(priv->dns_manager,
- new_config,
- NM_DNS_IP_CONFIG_TYPE_DEFAULT,
- device);
- if (old_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- old_config,
- NM_DNS_IP_CONFIG_TYPE_REMOVED);
- }
- update_ip_dns(self, addr_family, device);
- if (addr_family == AF_INET)
- update_ip4_routing(self, TRUE);
- else
- update_ip6_routing(self, TRUE);
- update_system_hostname(self, addr_family == AF_INET ? "ip4 conf" : "ip6 conf");
+ if (nm_device_get_state(device) < NM_DEVICE_STATE_DEACTIVATING) {
+ nm_dns_manager_set_ip_config(priv->dns_manager,
+ AF_UNSPEC,
+ device,
+ l3cd_new,
+ NM_DNS_IP_CONFIG_TYPE_DEFAULT,
+ TRUE);
+ update_ip_dns(self, AF_INET, device);
+ update_ip_dns(self, AF_INET6, device);
+ update_ip4_routing(self, TRUE);
+ update_ip6_routing(self, TRUE);
+ update_system_hostname(self, "ip conf");
} else {
- /* Old configs get removed immediately */
- if (old_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- old_config,
- NM_DNS_IP_CONFIG_TYPE_REMOVED);
+ nm_dns_manager_set_ip_config(priv->dns_manager,
+ AF_UNSPEC,
+ device,
+ l3cd_old,
+ NM_DNS_IP_CONFIG_TYPE_REMOVED,
+ TRUE);
}
nm_dns_manager_end_updates(priv->dns_manager, __func__);
@@ -2225,14 +2171,7 @@ devices_list_register(NMPolicy *self, NMDevice *device)
/* Connect state-changed with _after, so that the handler is invoked after other handlers. */
g_signal_connect_after(device, NM_DEVICE_STATE_CHANGED, G_CALLBACK(device_state_changed), priv);
- g_signal_connect(device,
- NM_DEVICE_IP4_CONFIG_CHANGED,
- G_CALLBACK(device_ip_config_changed),
- priv);
- g_signal_connect(device,
- NM_DEVICE_IP6_CONFIG_CHANGED,
- G_CALLBACK(device_ip_config_changed),
- priv);
+ g_signal_connect(device, NM_DEVICE_L3CD_CHANGED, G_CALLBACK(device_l3cd_changed), priv);
g_signal_connect(device,
NM_DEVICE_IP6_PREFIX_DELEGATED,
G_CALLBACK(device_ip6_prefix_delegated),
@@ -2294,51 +2233,26 @@ device_removed(NMManager *manager, NMDevice *device, gpointer user_data)
/*****************************************************************************/
static void
-vpn_connection_activated(NMPolicy *self, NMVpnConnection *vpn)
-{
- NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
- NMIP4Config * ip4_config;
- NMIP6Config * ip6_config;
-
- nm_dns_manager_begin_updates(priv->dns_manager, __func__);
-
- ip4_config = nm_vpn_connection_get_ip4_config(vpn);
- if (ip4_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip4_config),
- NM_DNS_IP_CONFIG_TYPE_VPN);
-
- ip6_config = nm_vpn_connection_get_ip6_config(vpn);
- if (ip6_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip6_config),
- NM_DNS_IP_CONFIG_TYPE_VPN);
-
- update_routing_and_dns(self, TRUE, NULL);
-
- nm_dns_manager_end_updates(priv->dns_manager, __func__);
-}
-
-static void
-vpn_connection_deactivated(NMPolicy *self, NMVpnConnection *vpn)
+vpn_connection_update_dns(NMPolicy *self, NMVpnConnection *vpn, gboolean remove)
{
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
- NMIP4Config * ip4_config;
- NMIP6Config * ip6_config;
+ int IS_IPv4;
nm_dns_manager_begin_updates(priv->dns_manager, __func__);
- ip4_config = nm_vpn_connection_get_ip4_config(vpn);
- if (ip4_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip4_config),
- NM_DNS_IP_CONFIG_TYPE_REMOVED);
+ for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
+ int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
+ const NML3ConfigData *l3cd;
- ip6_config = nm_vpn_connection_get_ip6_config(vpn);
- if (ip6_config)
+ l3cd = nm_vpn_connection_get_l3cd(vpn, addr_family);
nm_dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip6_config),
- NM_DNS_IP_CONFIG_TYPE_REMOVED);
+ addr_family,
+ vpn,
+ l3cd,
+ remove ? NM_DNS_IP_CONFIG_TYPE_REMOVED
+ : NM_DNS_IP_CONFIG_TYPE_VPN,
+ TRUE);
+ }
update_routing_and_dns(self, TRUE, NULL);
@@ -2352,13 +2266,14 @@ vpn_connection_state_changed(NMVpnConnection * vpn,
NMActiveConnectionStateReason reason,
NMPolicy * self)
{
+ /* FIXME(l3cfg): we need to track changes to nm_vpn_connection_get_l3cd(). */
if (new_state == NM_VPN_CONNECTION_STATE_ACTIVATED)
- vpn_connection_activated(self, vpn);
+ vpn_connection_update_dns(self, vpn, FALSE);
else if (new_state >= NM_VPN_CONNECTION_STATE_FAILED) {
/* Only clean up IP/DNS if the connection ever got past IP_CONFIG */
if (old_state >= NM_VPN_CONNECTION_STATE_IP_CONFIG_GET
&& old_state <= NM_VPN_CONNECTION_STATE_ACTIVATED)
- vpn_connection_deactivated(self, vpn);
+ vpn_connection_update_dns(self, vpn, TRUE);
}
}
diff --git a/src/core/nm-proxy-config.c b/src/core/nm-proxy-config.c
deleted file mode 100644
index 49156dfae0..0000000000
--- a/src/core/nm-proxy-config.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "nm-proxy-config.h"
-
-#include <stdlib.h>
-
-#include "libnm-core-intern/nm-core-internal.h"
-
-/*****************************************************************************/
-
-typedef struct {
- NMProxyConfigMethod method;
- gboolean browser_only;
- char * pac_url;
- char * pac_script;
-} NMProxyConfigPrivate;
-
-struct _NMProxyConfig {
- GObject parent;
- NMProxyConfigPrivate _priv;
-};
-
-struct _NMProxyConfigClass {
- GObjectClass parent;
-};
-
-G_DEFINE_TYPE(NMProxyConfig, nm_proxy_config, G_TYPE_OBJECT)
-
-#define NM_PROXY_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMProxyConfig, NM_IS_PROXY_CONFIG)
-
-/*****************************************************************************/
-
-void
-nm_proxy_config_set_method(NMProxyConfig *config, NMProxyConfigMethod method)
-{
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- priv->method = method;
-}
-
-NMProxyConfigMethod
-nm_proxy_config_get_method(const NMProxyConfig *config)
-{
- const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- return priv->method;
-}
-
-void
-nm_proxy_config_merge_setting(NMProxyConfig *config, NMSettingProxy *setting)
-{
- const char * tmp = NULL;
- NMProxyConfigPrivate *priv;
- NMSettingProxyMethod method;
-
- if (!setting)
- return;
-
- g_return_if_fail(NM_IS_SETTING_PROXY(setting));
-
- priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- nm_clear_g_free(&priv->pac_script);
-
- method = nm_setting_proxy_get_method(setting);
- switch (method) {
- case NM_SETTING_PROXY_METHOD_AUTO:
- priv->method = NM_PROXY_CONFIG_METHOD_AUTO;
-
- /* Free DHCP Obtained PAC Url (i.e Option 252)
- * only when libnm overrides it.
- */
- tmp = nm_setting_proxy_get_pac_url(setting);
- if (tmp) {
- g_free(priv->pac_url);
- priv->pac_url = g_strdup(tmp);
- }
-
- tmp = nm_setting_proxy_get_pac_script(setting);
- priv->pac_script = g_strdup(tmp);
-
- break;
- case NM_SETTING_PROXY_METHOD_NONE:
- priv->method = NM_PROXY_CONFIG_METHOD_NONE;
- break;
- }
-
- priv->browser_only = nm_setting_proxy_get_browser_only(setting);
-}
-
-gboolean
-nm_proxy_config_get_browser_only(const NMProxyConfig *config)
-{
- const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- return priv->browser_only;
-}
-
-void
-nm_proxy_config_set_pac_url(NMProxyConfig *config, const char *url)
-{
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- g_free(priv->pac_url);
- priv->pac_url = g_strdup(url);
-}
-
-const char *
-nm_proxy_config_get_pac_url(const NMProxyConfig *config)
-{
- const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- return priv->pac_url;
-}
-
-void
-nm_proxy_config_set_pac_script(NMProxyConfig *config, const char *script)
-{
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- g_free(priv->pac_script);
- priv->pac_script = g_strdup(script);
-}
-
-const char *
-nm_proxy_config_get_pac_script(const NMProxyConfig *config)
-{
- const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- return priv->pac_script;
-}
-
-/*****************************************************************************/
-
-static void
-nm_proxy_config_init(NMProxyConfig *config)
-{
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- priv->method = NM_PROXY_CONFIG_METHOD_NONE;
-}
-
-NMProxyConfig *
-nm_proxy_config_new(void)
-{
- return g_object_new(NM_TYPE_PROXY_CONFIG, NULL);
-}
-
-static void
-finalize(GObject *object)
-{
- NMProxyConfig * self = NM_PROXY_CONFIG(object);
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(self);
-
- g_free(priv->pac_url);
- g_free(priv->pac_script);
-
- G_OBJECT_CLASS(nm_proxy_config_parent_class)->finalize(object);
-}
-
-static void
-nm_proxy_config_class_init(NMProxyConfigClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
-
- object_class->finalize = finalize;
-}
diff --git a/src/core/nm-proxy-config.h b/src/core/nm-proxy-config.h
deleted file mode 100644
index 7b6241f849..0000000000
--- a/src/core/nm-proxy-config.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>.
- */
-
-#ifndef __NETWORKMANAGER_PROXY_CONFIG_H__
-#define __NETWORKMANAGER_PROXY_CONFIG_H__
-
-#include "nm-setting-proxy.h"
-#include "nm-l3-config-data.h"
-
-#define NM_TYPE_PROXY_CONFIG (nm_proxy_config_get_type())
-#define NM_PROXY_CONFIG(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_PROXY_CONFIG, NMProxyConfig))
-#define NM_PROXY_CONFIG_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_PROXY_CONFIG, NMProxyConfigClass))
-#define NM_IS_PROXY_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_PROXY_CONFIG))
-#define NM_IS_PROXY_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_PROXY_CONFIG))
-#define NM_PROXY_CONFIG_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_PROXY_CONFIG, NMProxyConfigClass))
-
-typedef struct _NMProxyConfigClass NMProxyConfigClass;
-
-GType nm_proxy_config_get_type(void);
-
-NMProxyConfig *nm_proxy_config_new(void);
-
-void nm_proxy_config_set_method(NMProxyConfig *config, NMProxyConfigMethod method);
-NMProxyConfigMethod nm_proxy_config_get_method(const NMProxyConfig *config);
-
-void nm_proxy_config_merge_setting(NMProxyConfig *config, NMSettingProxy *setting);
-
-gboolean nm_proxy_config_get_browser_only(const NMProxyConfig *config);
-
-void nm_proxy_config_set_pac_url(NMProxyConfig *config, const char *url);
-const char *nm_proxy_config_get_pac_url(const NMProxyConfig *config);
-
-void nm_proxy_config_set_pac_script(NMProxyConfig *config, const char *script);
-const char *nm_proxy_config_get_pac_script(const NMProxyConfig *config);
-
-#endif /* __NETWORKMANAGER_PROXY_CONFIG_H__ */
diff --git a/src/core/nm-types.h b/src/core/nm-types.h
index 294cf40936..76287e4dbf 100644
--- a/src/core/nm-types.h
+++ b/src/core/nm-types.h
@@ -25,10 +25,7 @@ typedef struct _NML3Cfg NML3Cfg;
typedef struct _NML3ConfigData NML3ConfigData;
typedef struct _NMDevice NMDevice;
typedef struct _NMDhcpConfig NMDhcpConfig;
-typedef struct _NMProxyConfig NMProxyConfig;
typedef struct _NMIPConfig NMIPConfig;
-typedef struct _NMIP4Config NMIP4Config;
-typedef struct _NMIP6Config NMIP6Config;
typedef struct _NMManager NMManager;
typedef struct _NMNetns NMNetns;
typedef struct _NMPolicy NMPolicy;
diff --git a/src/core/platform/nm-fake-platform.c b/src/core/platform/nm-fake-platform.c
index b773df9a43..870350c5ca 100644
--- a/src/core/platform/nm-fake-platform.c
+++ b/src/core/platform/nm-fake-platform.c
@@ -1118,8 +1118,6 @@ ip_route_add(NMPlatform * platform,
(const NMPlatformObject *) route);
r = NMP_OBJECT_CAST_IP_ROUTE(obj);
- r->is_external = TRUE;
-
nm_platform_ip_route_normalize(addr_family, r);
switch (addr_family) {
diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c
index 4b1db7fad7..2b9b2f8f67 100644
--- a/src/core/platform/tests/test-route.c
+++ b/src/core/platform/tests/test-route.c
@@ -332,33 +332,30 @@ test_ip4_route(void)
/* Test route listing */
routes = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, ifindex);
memset(rts, 0, sizeof(rts));
- rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
- rts[0].network = gateway;
- rts[0].plen = 32;
- rts[0].ifindex = ifindex;
- rts[0].gateway = INADDR_ANY;
- rts[0].metric = metric;
- rts[0].mss = mss;
- rts[0].is_external = TRUE;
- rts[0].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_LINK);
- rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
- rts[1].network = network;
- rts[1].plen = plen;
- rts[1].ifindex = ifindex;
- rts[1].gateway = gateway;
- rts[1].metric = metric;
- rts[1].mss = mss;
- rts[1].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE);
- rts[1].is_external = TRUE;
- rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
- rts[2].network = 0;
- rts[2].plen = 0;
- rts[2].ifindex = ifindex;
- rts[2].gateway = gateway;
- rts[2].metric = metric;
- rts[2].mss = mss;
- rts[2].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE);
- rts[2].is_external = TRUE;
+ rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
+ rts[0].network = gateway;
+ rts[0].plen = 32;
+ rts[0].ifindex = ifindex;
+ rts[0].gateway = INADDR_ANY;
+ rts[0].metric = metric;
+ rts[0].mss = mss;
+ rts[0].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_LINK);
+ rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
+ rts[1].network = network;
+ rts[1].plen = plen;
+ rts[1].ifindex = ifindex;
+ rts[1].gateway = gateway;
+ rts[1].metric = metric;
+ rts[1].mss = mss;
+ rts[1].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE);
+ rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
+ rts[2].network = 0;
+ rts[2].plen = 0;
+ rts[2].ifindex = ifindex;
+ rts[2].gateway = gateway;
+ rts[2].metric = metric;
+ rts[2].mss = mss;
+ rts[2].scope_inv = nm_platform_route_scope_inv(RT_SCOPE_UNIVERSE);
g_assert_cmpint(routes->len, ==, 3);
nmtst_platform_ip4_routes_equal_aptr((const NMPObject *const *) routes->pdata,
rts,
@@ -492,33 +489,30 @@ test_ip6_route(void)
/* Test route listing */
routes = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, ifindex);
memset(rts, 0, sizeof(rts));
- rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
- rts[0].network = gateway;
- rts[0].plen = 128;
- rts[0].ifindex = ifindex;
- rts[0].gateway = in6addr_any;
- rts[0].pref_src = in6addr_any;
- rts[0].metric = metric;
- rts[0].mss = mss;
- rts[0].is_external = TRUE;
- rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
- rts[1].network = network;
- rts[1].plen = plen;
- rts[1].ifindex = ifindex;
- rts[1].gateway = gateway;
- rts[1].pref_src = pref_src;
- rts[1].metric = metric;
- rts[1].mss = mss;
- rts[1].is_external = TRUE;
- rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
- rts[2].network = in6addr_any;
- rts[2].plen = 0;
- rts[2].ifindex = ifindex;
- rts[2].gateway = gateway;
- rts[2].pref_src = in6addr_any;
- rts[2].metric = metric;
- rts[2].mss = mss;
- rts[2].is_external = TRUE;
+ rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
+ rts[0].network = gateway;
+ rts[0].plen = 128;
+ rts[0].ifindex = ifindex;
+ rts[0].gateway = in6addr_any;
+ rts[0].pref_src = in6addr_any;
+ rts[0].metric = metric;
+ rts[0].mss = mss;
+ rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
+ rts[1].network = network;
+ rts[1].plen = plen;
+ rts[1].ifindex = ifindex;
+ rts[1].gateway = gateway;
+ rts[1].pref_src = pref_src;
+ rts[1].metric = metric;
+ rts[1].mss = mss;
+ rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER);
+ rts[2].network = in6addr_any;
+ rts[2].plen = 0;
+ rts[2].ifindex = ifindex;
+ rts[2].gateway = gateway;
+ rts[2].pref_src = in6addr_any;
+ rts[2].metric = metric;
+ rts[2].mss = mss;
g_assert_cmpint(routes->len, ==, 3);
nmtst_platform_ip6_routes_equal_aptr((const NMPObject *const *) routes->pdata,
rts,
@@ -715,7 +709,6 @@ test_ip4_route_options(gconstpointer test_data)
for (i = 0; i < rts_n; i++) {
rts_cmp[i] = rts_add[i];
nm_platform_ip_route_normalize(AF_INET, NM_PLATFORM_IP_ROUTE_CAST(&rts_cmp[i]));
- rts_cmp[i].is_external = TRUE;
}
routes = nmtstp_ip4_route_get_all(NM_PLATFORM_GET, IFINDEX);
@@ -887,7 +880,6 @@ test_ip6_route_options(gconstpointer test_data)
for (i = 0; i < rts_n; i++) {
rts_cmp[i] = rts_add[i];
nm_platform_ip_route_normalize(AF_INET6, NM_PLATFORM_IP_ROUTE_CAST(&rts_cmp[i]));
- rts_cmp[i].is_external = TRUE;
}
routes = nmtstp_ip6_route_get_all(NM_PLATFORM_GET, IFINDEX);
diff --git a/src/core/ppp/nm-ppp-manager-call.c b/src/core/ppp/nm-ppp-manager-call.c
index 5e84f59610..8adeb8adbe 100644
--- a/src/core/ppp/nm-ppp-manager-call.c
+++ b/src/core/ppp/nm-ppp-manager-call.c
@@ -94,24 +94,6 @@ again:
return ret;
}
-void
-nm_ppp_manager_set_route_parameters(NMPPPManager *self,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric)
-{
- const NMPPPOps *ppp_ops = ppp_ops_get();
-
- g_return_if_fail(ppp_ops);
-
- ppp_ops->set_route_parameters(self,
- ip4_route_table,
- ip4_route_metric,
- ip6_route_table,
- ip6_route_metric);
-}
-
gboolean
nm_ppp_manager_start(NMPPPManager *self,
NMActRequest *req,
diff --git a/src/core/ppp/nm-ppp-manager-call.h b/src/core/ppp/nm-ppp-manager-call.h
index c831cf0d61..87d2f93f55 100644
--- a/src/core/ppp/nm-ppp-manager-call.h
+++ b/src/core/ppp/nm-ppp-manager-call.h
@@ -10,12 +10,6 @@
NMPPPManager *nm_ppp_manager_create(const char *iface, GError **error);
-void nm_ppp_manager_set_route_parameters(NMPPPManager *ppp_manager,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric);
-
gboolean nm_ppp_manager_start(NMPPPManager *self,
NMActRequest *req,
const char * ppp_name,
diff --git a/src/core/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c
index e6790f2260..bf00c429e8 100644
--- a/src/core/ppp/nm-ppp-manager.c
+++ b/src/core/ppp/nm-ppp-manager.c
@@ -32,8 +32,7 @@
#include "libnm-platform/nm-platform-utils.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "nm-l3-config-data.h"
#include "nm-dbus-object.h"
#include "nm-pppd-plugin.h"
@@ -46,6 +45,26 @@ static NM_CACHED_QUARK_FCN("ppp-manager-secret-tries", ppp_manager_secret_tries_
/*****************************************************************************/
+/* FIXME(l3cfg:ppp): I think NMPPPManager's API should be improved to be easier
+ * usable (by the higher layers). That means to make the class more complex, to
+ * provide a simpler API.
+ *
+ * For example:
+ *
+ * - NM_PPP_MANAGER_SIGNAL_STATE_CHANGED just gets re-emitted when we receive
+ * the D-Bus call from the plugin. The emitted state is like NM_PPP_STATUS_SERIALCONN,
+ * but none of the users cares about this (what would it mean anyway)? The
+ * class should itself consume the state, and emit something more consumable
+ * (like: interface is ready (with ifindex), IPvX configuration done (with l3cd).
+ *
+ * - currently signals can be emitted in any order, and it's not clear which
+ * signals we can expect. For example, when we activate a device, we may want to wait
+ * for IPv4 and IPv6 configuration, but it's not clear whether this configuration
+ * is still to be received or whether we can stop waiting.
+ **/
+
+/*****************************************************************************/
+
#define NM_TYPE_PPP_MANAGER (nm_ppp_manager_get_type())
#define NM_PPP_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_PPP_MANAGER, NMPPPManager))
#define NM_PPP_MANAGER_CLASS(klass) \
@@ -62,8 +81,7 @@ GType nm_ppp_manager_get_type(void);
enum {
STATE_CHANGED,
IFINDEX_SET,
- IP4_CONFIG,
- IP6_CONFIG,
+ NEW_CONFIG,
STATS,
LAST_SIGNAL
@@ -91,11 +109,6 @@ typedef struct {
/* Monitoring */
int monitor_fd;
guint monitor_id;
-
- guint32 ip4_route_table;
- guint32 ip4_route_metric;
- guint32 ip6_route_table;
- guint32 ip6_route_metric;
} NMPPPManagerPrivate;
struct _NMPPPManager {
@@ -131,30 +144,19 @@ static void _ppp_manager_stop_cancel(NMPPPManagerStopHandle *handle);
/*****************************************************************************/
static void
-_ppp_manager_set_route_parameters(NMPPPManager *self,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric)
+_emit_signal_new_config(NMPPPManager * self,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid)
{
- NMPPPManagerPrivate *priv;
+ nm_assert(NM_IS_PPP_MANAGER(self));
+ nm_assert_addr_family(addr_family);
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
+ nm_assert((!!iid) == (addr_family == AF_INET6));
- g_return_if_fail(NM_IS_PPP_MANAGER(self));
+ nm_l3_config_data_seal(l3cd);
- priv = NM_PPP_MANAGER_GET_PRIVATE(self);
- if (priv->ip4_route_table != ip4_route_table || priv->ip4_route_metric != ip4_route_metric
- || priv->ip6_route_table != ip6_route_table || priv->ip6_route_metric != ip6_route_metric) {
- priv->ip4_route_table = ip4_route_table;
- priv->ip4_route_metric = ip4_route_metric;
- priv->ip6_route_table = ip6_route_table;
- priv->ip6_route_metric = ip6_route_metric;
-
- _LOGT("route-parameters: table-v4: %u, metric-v4: %u, table-v6: %u, metric-v6: %u",
- priv->ip4_route_table,
- priv->ip4_route_metric,
- priv->ip6_route_table,
- priv->ip6_route_metric);
- }
+ g_signal_emit(self, signals[NEW_CONFIG], 0, addr_family, l3cd, iid);
}
/*****************************************************************************/
@@ -510,12 +512,12 @@ impl_ppp_manager_set_ip4_config(NMDBusObject * obj,
GDBusMethodInvocation * invocation,
GVariant * parameters)
{
- NMPPPManager * self = NM_PPP_MANAGER(obj);
- NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE(self);
- gs_unref_object NMIP4Config *config = NULL;
- NMPlatformIP4Address address;
- guint32 u32, mtu;
- GVariantIter * iter;
+ NMPPPManager * self = NM_PPP_MANAGER(obj);
+ NMPPPManagerPrivate * priv = NM_PPP_MANAGER_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP4Address address;
+ guint32 u32, mtu;
+ GVariantIter * iter;
gs_unref_variant GVariant *config_dict = NULL;
_LOGI("(IPv4 Config Get) reply received.");
@@ -527,37 +529,41 @@ impl_ppp_manager_set_ip4_config(NMDBusObject * obj,
if (!set_ip_config_common(self, config_dict, &mtu))
goto out;
- config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), priv->ifindex);
+ l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
+ priv->ifindex,
+ NM_IP_CONFIG_SOURCE_PPP);
- if (mtu)
- nm_ip4_config_set_mtu(config, mtu, NM_IP_CONFIG_SOURCE_PPP);
+ nm_l3_config_data_set_mtu(l3cd, mtu);
- memset(&address, 0, sizeof(address));
- address.plen = 32;
+ address = (NMPlatformIP4Address){
+ .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_PREFIX, "u", &u32))
+ address.plen = u32;
+
if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_GATEWAY, "u", &u32)) {
const NMPlatformIP4Route r = {
.ifindex = priv->ifindex,
.rt_source = NM_IP_CONFIG_SOURCE_PPP,
.gateway = u32,
- .table_coerced = nm_platform_route_table_coerce(priv->ip4_route_table),
- .metric = priv->ip4_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
- nm_ip4_config_add_route(config, &r, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &r);
address.peer_address = u32;
} else
address.peer_address = address.address;
- if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_PREFIX, "u", &u32))
- address.plen = u32;
-
- if (address.address && address.plen && address.plen <= 32) {
+ if (address.address && address.plen > 0 && address.plen <= 32) {
address.addr_source = NM_IP_CONFIG_SOURCE_PPP;
- nm_ip4_config_add_address(config, &address);
+ nm_l3_config_data_add_address_4(l3cd, &address);
} else {
_LOGE("invalid IPv4 address received!");
goto out;
@@ -565,18 +571,17 @@ impl_ppp_manager_set_ip4_config(NMDBusObject * obj,
if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_DNS, "au", &iter)) {
while (g_variant_iter_next(iter, "u", &u32))
- nm_ip4_config_add_nameserver(config, u32);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &u32);
g_variant_iter_free(iter);
}
if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_WINS, "au", &iter)) {
while (g_variant_iter_next(iter, "u", &u32))
- nm_ip4_config_add_wins(config, u32);
+ nm_l3_config_data_add_wins(l3cd, u32);
g_variant_iter_free(iter);
}
- /* Push the IP4 config up to the device */
- g_signal_emit(self, signals[IP4_CONFIG], 0, config);
+ _emit_signal_new_config(self, AF_INET, l3cd, NULL);
out:
g_dbus_method_invocation_return_value(invocation, NULL);
@@ -620,14 +625,14 @@ impl_ppp_manager_set_ip6_config(NMDBusObject * obj,
GDBusMethodInvocation * invocation,
GVariant * parameters)
{
- NMPPPManager * self = NM_PPP_MANAGER(obj);
- NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE(self);
- gs_unref_object NMIP6Config *config = NULL;
- NMPlatformIP6Address addr;
- struct in6_addr a;
- NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
- gboolean has_peer = FALSE;
- gs_unref_variant GVariant *config_dict = NULL;
+ NMPPPManager * self = NM_PPP_MANAGER(obj);
+ NMPPPManagerPrivate * priv = NM_PPP_MANAGER_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP6Address address;
+ struct in6_addr a;
+ NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
+ gboolean has_peer = FALSE;
+ gs_unref_variant GVariant *config_dict = NULL;
_LOGI("(IPv6 Config Get) reply received.");
@@ -638,32 +643,36 @@ impl_ppp_manager_set_ip6_config(NMDBusObject * obj,
if (!set_ip_config_common(self, config_dict, NULL))
goto out;
- config = nm_ip6_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), priv->ifindex);
+ l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
+ priv->ifindex,
+ NM_IP_CONFIG_SOURCE_PPP);
- memset(&addr, 0, sizeof(addr));
- addr.plen = 64;
+ address = (NMPlatformIP6Address){
+ .plen = 64,
+ };
if (iid_value_to_ll6_addr(config_dict, NM_PPP_IP6_CONFIG_PEER_IID, &a, NULL)) {
const NMPlatformIP6Route r = {
.ifindex = priv->ifindex,
.rt_source = NM_IP_CONFIG_SOURCE_PPP,
.gateway = a,
- .table_coerced = nm_platform_route_table_coerce(priv->ip6_route_table),
- .metric = priv->ip6_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
- nm_ip6_config_add_route(config, &r, NULL);
- addr.peer_address = a;
- has_peer = TRUE;
+ nm_l3_config_data_add_route_6(l3cd, &r);
+ address.peer_address = a;
+ has_peer = TRUE;
}
- if (iid_value_to_ll6_addr(config_dict, NM_PPP_IP6_CONFIG_OUR_IID, &addr.address, &iid)) {
+ if (iid_value_to_ll6_addr(config_dict, NM_PPP_IP6_CONFIG_OUR_IID, &address.address, &iid)) {
if (!has_peer)
- addr.peer_address = addr.address;
- nm_ip6_config_add_address(config, &addr);
+ address.peer_address = address.address;
+ nm_l3_config_data_add_address_6(l3cd, &address);
- /* Push the IPv6 config and interface identifier up to the device */
- g_signal_emit(self, signals[IP6_CONFIG], 0, &iid, config);
+ _emit_signal_new_config(self, AF_INET6, l3cd, &iid);
} else
_LOGE("invalid IPv6 address received!");
@@ -1290,12 +1299,8 @@ nm_ppp_manager_init(NMPPPManager *self)
{
NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE(self);
- priv->ifindex = -1;
- priv->monitor_fd = -1;
- priv->ip4_route_table = RT_TABLE_MAIN;
- priv->ip4_route_metric = 460;
- priv->ip6_route_table = RT_TABLE_MAIN;
- priv->ip6_route_metric = 460;
+ priv->ifindex = -1;
+ priv->monitor_fd = -1;
}
static NMPPPManager *
@@ -1414,18 +1419,7 @@ nm_ppp_manager_class_init(NMPPPManagerClass *manager_class)
G_TYPE_INT,
G_TYPE_STRING);
- signals[IP4_CONFIG] = g_signal_new(NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 1,
- G_TYPE_OBJECT);
-
- signals[IP6_CONFIG] = g_signal_new(NM_PPP_MANAGER_SIGNAL_IP6_CONFIG,
+ signals[NEW_CONFIG] = g_signal_new(NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_FIRST,
0,
@@ -1433,9 +1427,10 @@ nm_ppp_manager_class_init(NMPPPManagerClass *manager_class)
NULL,
NULL,
G_TYPE_NONE,
- 2,
- G_TYPE_POINTER,
- G_TYPE_OBJECT);
+ 3,
+ G_TYPE_INT, /* addr_family */
+ G_TYPE_POINTER, /* (const NML3ConfigData *) */
+ G_TYPE_POINTER); /* (const NMUtilsIPv6IfaceId *) */
signals[STATS] = g_signal_new(NM_PPP_MANAGER_SIGNAL_STATS,
G_OBJECT_CLASS_TYPE(object_class),
@@ -1451,9 +1446,8 @@ nm_ppp_manager_class_init(NMPPPManagerClass *manager_class)
}
const NMPPPOps ppp_ops = {
- .create = _ppp_manager_new,
- .set_route_parameters = _ppp_manager_set_route_parameters,
- .start = _ppp_manager_start,
- .stop = _ppp_manager_stop,
- .stop_cancel = _ppp_manager_stop_cancel,
+ .create = _ppp_manager_new,
+ .start = _ppp_manager_start,
+ .stop = _ppp_manager_stop,
+ .stop_cancel = _ppp_manager_stop_cancel,
};
diff --git a/src/core/ppp/nm-ppp-manager.h b/src/core/ppp/nm-ppp-manager.h
index c41dda2074..9cf465517c 100644
--- a/src/core/ppp/nm-ppp-manager.h
+++ b/src/core/ppp/nm-ppp-manager.h
@@ -11,8 +11,7 @@
#define NM_PPP_MANAGER_SIGNAL_STATE_CHANGED "state-changed"
#define NM_PPP_MANAGER_SIGNAL_IFINDEX_SET "ifindex-set"
-#define NM_PPP_MANAGER_SIGNAL_IP4_CONFIG "ip4-config"
-#define NM_PPP_MANAGER_SIGNAL_IP6_CONFIG "ip6-config"
+#define NM_PPP_MANAGER_SIGNAL_NEW_CONFIG "new-config"
#define NM_PPP_MANAGER_SIGNAL_STATS "stats"
typedef struct _NMPPPManager NMPPPManager;
diff --git a/src/core/ppp/nm-ppp-plugin-api.h b/src/core/ppp/nm-ppp-plugin-api.h
index 647e1c240e..a867b94920 100644
--- a/src/core/ppp/nm-ppp-plugin-api.h
+++ b/src/core/ppp/nm-ppp-plugin-api.h
@@ -11,12 +11,6 @@
typedef const struct {
NMPPPManager *(*create)(const char *iface);
- void (*set_route_parameters)(NMPPPManager *manager,
- guint32 route_table_v4,
- guint32 route_metric_v4,
- guint32 route_table_v6,
- guint32 route_metric_v6);
-
gboolean (*start)(NMPPPManager *manager,
NMActRequest *req,
const char * ppp_name,
diff --git a/src/core/tests/meson.build b/src/core/tests/meson.build
index 99fa0ae9a1..78c689f798 100644
--- a/src/core/tests/meson.build
+++ b/src/core/tests/meson.build
@@ -6,8 +6,6 @@ test_units = [
'test-core',
'test-core-with-expect',
'test-dcb',
- 'test-ip4-config',
- 'test-ip6-config',
'test-l3cfg',
'test-utils',
'test-wired-defname',
diff --git a/src/core/tests/test-ip4-config.c b/src/core/tests/test-ip4-config.c
deleted file mode 100644
index 3a095d4ad9..0000000000
--- a/src/core/tests/test-ip4-config.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2013 - 2014 Red Hat, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include <arpa/inet.h>
-
-#include "nm-ip4-config.h"
-#include "libnm-platform/nm-platform.h"
-
-#include "nm-test-utils-core.h"
-
-static NMIP4Config *
-build_test_config(void)
-{
- NMIP4Config * config;
- NMPlatformIP4Address addr;
- NMPlatformIP4Route route;
-
- /* Build up the config to subtract */
- config = nmtst_ip4_config_new(1);
-
- nm_assert(NM_IP_CONFIG_CAST(config));
-
- addr = *nmtst_platform_ip4_address("192.168.1.10", "1.2.3.4", 24);
- nm_ip4_config_add_address(config, &addr);
-
- route = *nmtst_platform_ip4_route("10.0.0.0", 8, "192.168.1.1");
- nm_ip4_config_add_route(config, &route, NULL);
-
- route = *nmtst_platform_ip4_route("172.16.0.0", 16, "192.168.1.1");
- nm_ip4_config_add_route(config, &route, NULL);
-
- {
- const NMPlatformIP4Route r = {
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .gateway = nmtst_inet4_from_string("192.168.1.1"),
- .table_coerced = 0,
- .metric = 100,
- };
-
- nm_ip4_config_add_route(config, &r, NULL);
- }
-
- nm_ip4_config_add_nameserver(config, nmtst_inet4_from_string("4.2.2.1"));
- nm_ip4_config_add_nameserver(config, nmtst_inet4_from_string("4.2.2.2"));
- nm_ip4_config_add_domain(config, "foobar.com");
- nm_ip4_config_add_domain(config, "baz.com");
- nm_ip4_config_add_search(config, "blahblah.com");
- nm_ip4_config_add_search(config, "beatbox.com");
-
- nm_ip4_config_add_nis_server(config, nmtst_inet4_from_string("1.2.3.9"));
- nm_ip4_config_add_nis_server(config, nmtst_inet4_from_string("1.2.3.10"));
-
- nm_ip4_config_add_wins(config, nmtst_inet4_from_string("4.2.3.9"));
- nm_ip4_config_add_wins(config, nmtst_inet4_from_string("4.2.3.10"));
-
- return config;
-}
-
-static void
-test_replace(void)
-{
- gs_unref_object NMIP4Config *config1 = NULL;
- gs_unref_object NMIP4Config *config2 = NULL;
- NMPlatformIP4Address addr;
- gboolean relevant_changes;
-
- config1 = nmtst_ip4_config_new(1);
-
- addr = *nmtst_platform_ip4_address("172.16.0.1", NULL, 24);
- addr.timestamp = 10;
- addr.preferred = 3600;
- addr.lifetime = 7200;
- nm_ip4_config_add_address(config1, &addr);
-
- addr = *nmtst_platform_ip4_address("172.16.0.2", NULL, 24);
- addr.timestamp = 10;
- addr.preferred = 3600;
- addr.lifetime = 7200;
- nm_ip4_config_add_address(config1, &addr);
-
- config2 = nmtst_ip4_config_new(1);
-
- addr = *nmtst_platform_ip4_address("192.168.1.1", NULL, 24);
- addr.timestamp = 40;
- addr.preferred = 60;
- addr.lifetime = 120;
- nm_ip4_config_add_address(config2, &addr);
-
- addr = *nmtst_platform_ip4_address("172.16.0.2", NULL, 24);
- addr.timestamp = 40;
- addr.preferred = 60;
- addr.lifetime = 120;
- nm_ip4_config_add_address(config2, &addr);
-
- g_assert(nm_ip4_config_replace(config2, config1, &relevant_changes));
- g_assert(relevant_changes);
- g_assert(nm_ip4_config_equal(config1, config2));
-}
-
-static void
-test_subtract(void)
-{
- NMIP4Config * src, *dst;
- NMPlatformIP4Address addr;
- NMPlatformIP4Route route;
- const NMPlatformIP4Address *test_addr;
- const NMPlatformIP4Route * test_route;
- const char * expected_addr = "192.168.1.12";
- guint32 expected_addr_plen = 24;
- const char * expected_route_dest = "8.0.0.0";
- guint32 expected_route_plen = 8;
- const char * expected_route_next_hop = "192.168.1.1";
- guint32 expected_ns1 = nmtst_inet4_from_string("8.8.8.8");
- guint32 expected_ns2 = nmtst_inet4_from_string("8.8.8.9");
- const char * expected_domain = "wonderfalls.com";
- const char * expected_search = "somewhere.com";
- guint32 expected_nis = nmtst_inet4_from_string("1.2.3.13");
- guint32 expected_wins = nmtst_inet4_from_string("2.3.4.5");
- guint32 expected_mtu = 1492;
-
- src = build_test_config();
-
- /* add a couple more things to the test config */
- dst = build_test_config();
- addr = *nmtst_platform_ip4_address(expected_addr, NULL, expected_addr_plen);
- nm_ip4_config_add_address(dst, &addr);
-
- route = *nmtst_platform_ip4_route(expected_route_dest,
- expected_route_plen,
- expected_route_next_hop);
- nm_ip4_config_add_route(dst, &route, NULL);
-
- nm_ip4_config_add_nameserver(dst, expected_ns1);
- nm_ip4_config_add_nameserver(dst, expected_ns2);
- nm_ip4_config_add_domain(dst, expected_domain);
- nm_ip4_config_add_search(dst, expected_search);
-
- nm_ip4_config_add_nis_server(dst, expected_nis);
- nm_ip4_config_add_wins(dst, expected_wins);
-
- nm_ip4_config_set_mtu(dst, expected_mtu, NM_IP_CONFIG_SOURCE_UNKNOWN);
-
- nm_ip4_config_subtract(dst, src, 0);
-
- /* ensure what's left is what we expect */
- g_assert_cmpuint(nm_ip4_config_get_num_addresses(dst), ==, 1);
- test_addr = _nmtst_ip4_config_get_address(dst, 0);
- g_assert(test_addr != NULL);
- g_assert_cmpuint(test_addr->address, ==, nmtst_inet4_from_string(expected_addr));
- g_assert_cmpuint(test_addr->peer_address, ==, test_addr->address);
- g_assert_cmpuint(test_addr->plen, ==, expected_addr_plen);
-
- g_assert(!nm_ip4_config_best_default_route_get(dst));
- g_assert_cmpuint(nmtst_ip4_config_get_gateway(dst), ==, 0);
-
- g_assert_cmpuint(nm_ip4_config_get_num_routes(dst), ==, 1);
- test_route = _nmtst_ip4_config_get_route(dst, 0);
- g_assert(test_route != NULL);
- g_assert_cmpuint(test_route->network, ==, nmtst_inet4_from_string(expected_route_dest));
- g_assert_cmpuint(test_route->plen, ==, expected_route_plen);
- g_assert_cmpuint(test_route->gateway, ==, nmtst_inet4_from_string(expected_route_next_hop));
-
- g_assert_cmpuint(nm_ip4_config_get_num_nameservers(dst), ==, 2);
- g_assert_cmpuint(nm_ip4_config_get_nameserver(dst, 0), ==, expected_ns1);
- g_assert_cmpuint(nm_ip4_config_get_nameserver(dst, 1), ==, expected_ns2);
-
- g_assert_cmpuint(nm_ip4_config_get_num_domains(dst), ==, 1);
- g_assert_cmpstr(nm_ip4_config_get_domain(dst, 0), ==, expected_domain);
- g_assert_cmpuint(nm_ip4_config_get_num_searches(dst), ==, 1);
- g_assert_cmpstr(nm_ip4_config_get_search(dst, 0), ==, expected_search);
-
- g_assert_cmpuint(nm_ip4_config_get_num_nis_servers(dst), ==, 1);
- g_assert_cmpuint(nm_ip4_config_get_nis_server(dst, 0), ==, expected_nis);
-
- g_assert_cmpuint(nm_ip4_config_get_num_wins(dst), ==, 1);
- g_assert_cmpuint(nm_ip4_config_get_wins(dst, 0), ==, expected_wins);
-
- g_assert_cmpuint(nm_ip4_config_get_mtu(dst), ==, expected_mtu);
-
- g_object_unref(src);
- g_object_unref(dst);
-}
-
-static void
-test_compare_with_source(void)
-{
- NMIP4Config * a, *b;
- NMPlatformIP4Address addr;
- NMPlatformIP4Route route;
-
- a = nmtst_ip4_config_new(1);
- b = nmtst_ip4_config_new(2);
-
- /* Address */
- addr = *nmtst_platform_ip4_address("1.2.3.4", NULL, 24);
- addr.addr_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip4_config_add_address(a, &addr);
-
- addr.addr_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip4_config_add_address(b, &addr);
-
- /* Route */
- route = *nmtst_platform_ip4_route("10.0.0.0", 8, "192.168.1.1");
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip4_config_add_route(a, &route, NULL);
-
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip4_config_add_route(b, &route, NULL);
-
- /* Assert that the configs are basically the same, eg that the source is ignored */
- g_assert(nm_ip4_config_equal(a, b));
-
- g_object_unref(a);
- g_object_unref(b);
-}
-
-static void
-test_add_address_with_source(void)
-{
- NMIP4Config * a;
- NMPlatformIP4Address addr;
- const NMPlatformIP4Address *test_addr;
-
- a = nmtst_ip4_config_new(1);
-
- /* Test that a higher priority source is not overwritten */
- addr = *nmtst_platform_ip4_address("1.2.3.4", NULL, 24);
- addr.addr_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip4_config_add_address(a, &addr);
-
- test_addr = _nmtst_ip4_config_get_address(a, 0);
- g_assert_cmpint(test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- addr.addr_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip4_config_add_address(a, &addr);
-
- test_addr = _nmtst_ip4_config_get_address(a, 0);
- g_assert_cmpint(test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- /* Test that a lower priority address source is overwritten */
- _nmtst_ip4_config_del_address(a, 0);
- addr.addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
- nm_ip4_config_add_address(a, &addr);
-
- test_addr = _nmtst_ip4_config_get_address(a, 0);
- g_assert_cmpint(test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_KERNEL);
-
- addr.addr_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip4_config_add_address(a, &addr);
-
- test_addr = _nmtst_ip4_config_get_address(a, 0);
- g_assert_cmpint(test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- g_object_unref(a);
-}
-
-static void
-test_add_route_with_source(void)
-{
- gs_unref_object NMIP4Config *a = NULL;
- NMPlatformIP4Route route;
- const NMPlatformIP4Route * test_route;
-
- a = nmtst_ip4_config_new(1);
-
- /* Test that a higher priority source is not overwritten */
- route = *nmtst_platform_ip4_route("1.2.3.0", 24, "1.2.3.1");
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip4_config_add_route(a, &route, NULL);
-
- g_assert_cmpint(nm_ip4_config_get_num_routes(a), ==, 1);
- test_route = _nmtst_ip4_config_get_route(a, 0);
- g_assert_cmpint(test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip4_config_add_route(a, &route, NULL);
-
- g_assert_cmpint(nm_ip4_config_get_num_routes(a), ==, 1);
- test_route = _nmtst_ip4_config_get_route(a, 0);
- g_assert_cmpint(test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- _nmtst_ip4_config_del_route(a, 0);
- g_assert_cmpint(nm_ip4_config_get_num_routes(a), ==, 0);
-
- /* Test that a lower priority address source is overwritten */
- route.rt_source = NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
- nm_ip4_config_add_route(a, &route, NULL);
-
- g_assert_cmpint(nm_ip4_config_get_num_routes(a), ==, 1);
- test_route = _nmtst_ip4_config_get_route(a, 0);
- g_assert_cmpint(test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_RTPROT_KERNEL);
-
- route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
- nm_ip4_config_add_route(a, &route, NULL);
-
- g_assert_cmpint(nm_ip4_config_get_num_routes(a), ==, 1);
- test_route = _nmtst_ip4_config_get_route(a, 0);
- g_assert_cmpint(test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_KERNEL);
-}
-
-static void
-test_merge_subtract_mtu(void)
-{
- NMIP4Config *cfg1, *cfg2, *cfg3;
- guint32 expected_mtu2 = 1492;
- guint32 expected_mtu3 = 666;
-
- cfg1 = build_test_config();
- cfg2 = build_test_config();
- cfg3 = build_test_config();
-
- /* add MSS, MTU to configs to test them */
- nm_ip4_config_set_mtu(cfg2, expected_mtu2, NM_IP_CONFIG_SOURCE_UNKNOWN);
- nm_ip4_config_set_mtu(cfg3, expected_mtu3, NM_IP_CONFIG_SOURCE_UNKNOWN);
-
- nm_ip4_config_merge(cfg1, cfg2, NM_IP_CONFIG_MERGE_DEFAULT, 0);
- /* ensure MSS and MTU are in cfg1 */
- g_assert_cmpuint(nm_ip4_config_get_mtu(cfg1), ==, expected_mtu2);
-
- nm_ip4_config_merge(cfg1, cfg3, NM_IP_CONFIG_MERGE_DEFAULT, 0);
- /* ensure again the MSS and MTU in cfg1 got overridden */
- g_assert_cmpuint(nm_ip4_config_get_mtu(cfg1), ==, expected_mtu3);
-
- nm_ip4_config_subtract(cfg1, cfg3, 0);
- /* ensure MSS and MTU are zero in cfg1 */
- g_assert_cmpuint(nm_ip4_config_get_mtu(cfg1), ==, 0);
-
- g_object_unref(cfg1);
- g_object_unref(cfg2);
- g_object_unref(cfg3);
-}
-
-static void
-test_strip_search_trailing_dot(void)
-{
- NMIP4Config *config;
-
- config = nmtst_ip4_config_new(1);
-
- nm_ip4_config_add_search(config, ".");
- nm_ip4_config_add_search(config, "foo");
- nm_ip4_config_add_search(config, "bar.");
- nm_ip4_config_add_search(config, "baz.com");
- nm_ip4_config_add_search(config, "baz.com.");
- nm_ip4_config_add_search(config, "foobar..");
- nm_ip4_config_add_search(config, ".foobar");
- nm_ip4_config_add_search(config, "~.");
-
- g_assert_cmpuint(nm_ip4_config_get_num_searches(config), ==, 4);
- g_assert_cmpstr(nm_ip4_config_get_search(config, 0), ==, "foo");
- g_assert_cmpstr(nm_ip4_config_get_search(config, 1), ==, "bar");
- g_assert_cmpstr(nm_ip4_config_get_search(config, 2), ==, "baz.com");
- g_assert_cmpstr(nm_ip4_config_get_search(config, 3), ==, "~");
-
- g_object_unref(config);
-}
-
-/*****************************************************************************/
-
-NMTST_DEFINE();
-
-int
-main(int argc, char **argv)
-{
- nmtst_init_with_logging(&argc, &argv, NULL, "DEFAULT");
-
- g_test_add_func("/ip4-config/replace", test_replace);
- g_test_add_func("/ip4-config/subtract", test_subtract);
- g_test_add_func("/ip4-config/compare-with-source", test_compare_with_source);
- g_test_add_func("/ip4-config/add-address-with-source", test_add_address_with_source);
- g_test_add_func("/ip4-config/add-route-with-source", test_add_route_with_source);
- g_test_add_func("/ip4-config/merge-subtract-mtu", test_merge_subtract_mtu);
- g_test_add_func("/ip4-config/strip-search-trailing-dot", test_strip_search_trailing_dot);
-
- return g_test_run();
-}
diff --git a/src/core/tests/test-ip6-config.c b/src/core/tests/test-ip6-config.c
deleted file mode 100644
index 2e6d8aaa19..0000000000
--- a/src/core/tests/test-ip6-config.c
+++ /dev/null
@@ -1,538 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2013 Red Hat, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include <arpa/inet.h>
-#include <linux/if_addr.h>
-
-#include "nm-ip6-config.h"
-
-#include "libnm-platform/nm-platform.h"
-#include "nm-test-utils-core.h"
-
-static NMIP6Config *
-build_test_config(void)
-{
- NMIP6Config *config;
-
- /* Build up the config to subtract */
- config = nmtst_ip6_config_new(1);
-
- nm_ip6_config_add_address(config,
- nmtst_platform_ip6_address("abcd:1234:4321::cdde", "1:2:3:4::5", 64));
- nm_ip6_config_add_route(
- config,
- nmtst_platform_ip6_route("abcd:1200::", 24, "abcd:1234:4321:cdde::2", NULL),
- NULL);
- nm_ip6_config_add_route(config,
- nmtst_platform_ip6_route("2001::", 16, "2001:abba::2234", NULL),
- NULL);
-
- nm_ip6_config_add_route(config,
- nmtst_platform_ip6_route("::", 0, "3001:abba::3234", NULL),
- NULL);
-
- nm_ip6_config_add_nameserver(config, nmtst_inet6_from_string("1:2:3:4::1"));
- nm_ip6_config_add_nameserver(config, nmtst_inet6_from_string("1:2:3:4::2"));
- nm_ip6_config_add_domain(config, "foobar.com");
- nm_ip6_config_add_domain(config, "baz.com");
- nm_ip6_config_add_search(config, "blahblah.com");
- nm_ip6_config_add_search(config, "beatbox.com");
-
- return config;
-}
-
-static void
-test_subtract(void)
-{
- NMIP6Config * src, *dst;
- const NMPlatformIP6Address *test_addr;
- const NMPlatformIP6Route * test_route;
- const char * expected_addr = "1122:3344:5566::7788";
- guint32 expected_addr_plen = 96;
- const char * expected_route_dest = "9991:8800::";
- guint32 expected_route_plen = 24;
- const char * expected_route_next_hop = "1119:2228:3337:4446::5555";
- struct in6_addr expected_ns1;
- struct in6_addr expected_ns2;
- const char * expected_domain = "wonderfalls.com";
- const char * expected_search = "somewhere.com";
- struct in6_addr tmp;
-
- src = build_test_config();
-
- /* add a couple more things to the test config */
- dst = build_test_config();
- nm_ip6_config_add_address(dst,
- nmtst_platform_ip6_address(expected_addr, NULL, expected_addr_plen));
- nm_ip6_config_add_route(dst,
- nmtst_platform_ip6_route(expected_route_dest,
- expected_route_plen,
- expected_route_next_hop,
- NULL),
- NULL);
-
- expected_ns1 = *nmtst_inet6_from_string("2222:3333:4444::5555");
- nm_ip6_config_add_nameserver(dst, &expected_ns1);
- expected_ns2 = *nmtst_inet6_from_string("2222:3333:4444::5556");
- nm_ip6_config_add_nameserver(dst, &expected_ns2);
-
- nm_ip6_config_add_domain(dst, expected_domain);
- nm_ip6_config_add_search(dst, expected_search);
-
- nm_ip6_config_subtract(dst, src, 0);
-
- /* ensure what's left is what we expect */
- g_assert_cmpuint(nm_ip6_config_get_num_addresses(dst), ==, 1);
- test_addr = _nmtst_ip6_config_get_address(dst, 0);
- g_assert(test_addr != NULL);
- tmp = *nmtst_inet6_from_string(expected_addr);
- g_assert(memcmp(&test_addr->address, &tmp, sizeof(tmp)) == 0);
- g_assert(memcmp(&test_addr->peer_address, &in6addr_any, sizeof(tmp)) == 0);
- g_assert_cmpuint(test_addr->plen, ==, expected_addr_plen);
-
- g_assert(nm_ip6_config_best_default_route_get(dst) == NULL);
-
- g_assert_cmpuint(nm_ip6_config_get_num_routes(dst), ==, 1);
- test_route = _nmtst_ip6_config_get_route(dst, 0);
- g_assert(test_route != NULL);
-
- tmp = *nmtst_inet6_from_string(expected_route_dest);
- g_assert(memcmp(&test_route->network, &tmp, sizeof(tmp)) == 0);
- g_assert_cmpuint(test_route->plen, ==, expected_route_plen);
- tmp = *nmtst_inet6_from_string(expected_route_next_hop);
- g_assert(memcmp(&test_route->gateway, &tmp, sizeof(tmp)) == 0);
-
- g_assert_cmpuint(nm_ip6_config_get_num_nameservers(dst), ==, 2);
- g_assert(memcmp(nm_ip6_config_get_nameserver(dst, 0), &expected_ns1, sizeof(expected_ns1))
- == 0);
- g_assert(memcmp(nm_ip6_config_get_nameserver(dst, 1), &expected_ns2, sizeof(expected_ns2))
- == 0);
-
- g_assert_cmpuint(nm_ip6_config_get_num_domains(dst), ==, 1);
- g_assert_cmpstr(nm_ip6_config_get_domain(dst, 0), ==, expected_domain);
- g_assert_cmpuint(nm_ip6_config_get_num_searches(dst), ==, 1);
- g_assert_cmpstr(nm_ip6_config_get_search(dst, 0), ==, expected_search);
-
- g_object_unref(src);
- g_object_unref(dst);
-}
-
-static void
-test_compare_with_source(void)
-{
- NMIP6Config * a, *b;
- NMPlatformIP6Address addr;
- NMPlatformIP6Route route;
-
- a = nmtst_ip6_config_new(1);
- b = nmtst_ip6_config_new(2);
-
- /* Address */
- addr = *nmtst_platform_ip6_address("1122:3344:5566::7788", NULL, 64);
- addr.addr_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip6_config_add_address(a, &addr);
-
- addr.addr_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip6_config_add_address(b, &addr);
-
- /* Route */
- route = *nmtst_platform_ip6_route("abcd:1200::", 24, "abcd:1234:4321:cdde::2", NULL);
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip6_config_add_route(a, &route, NULL);
-
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip6_config_add_route(b, &route, NULL);
-
- /* Assert that the configs are basically the same, eg that the source is ignored */
- g_assert(nm_ip6_config_equal(a, b));
-
- g_object_unref(a);
- g_object_unref(b);
-}
-
-static void
-test_add_address_with_source(void)
-{
- NMIP6Config * a;
- NMPlatformIP6Address addr;
- const NMPlatformIP6Address *test_addr;
-
- a = nmtst_ip6_config_new(1);
-
- /* Test that a higher priority source is not overwritten */
- addr = *nmtst_platform_ip6_address("1122:3344:5566::7788", NULL, 64);
- addr.addr_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip6_config_add_address(a, &addr);
-
- test_addr = _nmtst_ip6_config_get_address(a, 0);
- g_assert_cmpint(test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- addr.addr_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip6_config_add_address(a, &addr);
-
- test_addr = _nmtst_ip6_config_get_address(a, 0);
- g_assert_cmpint(test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- /* Test that a lower priority address source is overwritten */
- _nmtst_ip6_config_del_address(a, 0);
- addr.addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
- nm_ip6_config_add_address(a, &addr);
-
- test_addr = _nmtst_ip6_config_get_address(a, 0);
- g_assert_cmpint(test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_KERNEL);
-
- addr.addr_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip6_config_add_address(a, &addr);
-
- test_addr = _nmtst_ip6_config_get_address(a, 0);
- g_assert_cmpint(test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- g_object_unref(a);
-}
-
-static void
-test_add_route_with_source(void)
-{
- gs_unref_object NMIP6Config *a = NULL;
- NMPlatformIP6Route route;
- const NMPlatformIP6Route * test_route;
-
- a = nmtst_ip6_config_new(1);
-
- /* Test that a higher priority source is not overwritten */
- route = *nmtst_platform_ip6_route("abcd:1200::", 24, "abcd:1234:4321:cdde::2", NULL);
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip6_config_add_route(a, &route, NULL);
-
- g_assert_cmpint(nm_ip6_config_get_num_routes(a), ==, 1);
- test_route = _nmtst_ip6_config_get_route(a, 0);
- g_assert_cmpint(test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip6_config_add_route(a, &route, NULL);
-
- g_assert_cmpint(nm_ip6_config_get_num_routes(a), ==, 1);
- test_route = _nmtst_ip6_config_get_route(a, 0);
- g_assert_cmpint(test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
-
- _nmtst_ip6_config_del_route(a, 0);
- g_assert_cmpint(nm_ip6_config_get_num_routes(a), ==, 0);
-
- /* Test that a lower priority address source is overwritten */
- route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
- nm_ip6_config_add_route(a, &route, NULL);
-
- g_assert_cmpint(nm_ip6_config_get_num_routes(a), ==, 1);
- test_route = _nmtst_ip6_config_get_route(a, 0);
- g_assert_cmpint(test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_KERNEL);
-
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
- nm_ip6_config_add_route(a, &route, NULL);
-
- g_assert_cmpint(nm_ip6_config_get_num_routes(a), ==, 1);
- test_route = _nmtst_ip6_config_get_route(a, 0);
- g_assert_cmpint(test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
-}
-
-static void
-test_nm_ip6_config_addresses_sort_check(NMIP6Config * config,
- NMSettingIP6ConfigPrivacy use_tempaddr,
- int repeat)
-{
- int addr_count = nm_ip6_config_get_num_addresses(config);
- int i, irepeat;
- NMIP6Config *copy, *copy2;
- int * idx = g_new(int, addr_count);
-
- nm_ip6_config_set_privacy(config, use_tempaddr);
- copy = nm_ip6_config_clone(config);
- g_assert(copy);
- copy2 = nm_ip6_config_clone(config);
- g_assert(copy2);
-
- /* initialize the array of indices, and keep shuffling them for every @repeat iteration. */
- for (i = 0; i < addr_count; i++)
- idx[i] = i;
-
- for (irepeat = 0; irepeat < repeat; irepeat++) {
- /* randomly shuffle the addresses. */
- nm_ip6_config_reset_addresses(copy);
- for (i = 0; i < addr_count; i++) {
- int j = g_rand_int_range(nmtst_get_rand(), i, addr_count);
-
- NM_SWAP(&idx[i], &idx[j]);
- nm_ip6_config_add_address(copy, _nmtst_ip6_config_get_address(config, idx[i]));
- }
-
- /* reorder them again */
- _nmtst_ip6_config_addresses_sort(copy);
-
- /* check equality using nm_ip6_config_equal() */
- if (!nm_ip6_config_equal(copy, config)) {
- g_message("%s", "SORTING yields unexpected output:");
- for (i = 0; i < addr_count; i++) {
- g_message(
- " >> [%d] = %s",
- i,
- nm_platform_ip6_address_to_string(_nmtst_ip6_config_get_address(config, i),
- NULL,
- 0));
- g_message(" << [%d] = %s",
- i,
- nm_platform_ip6_address_to_string(_nmtst_ip6_config_get_address(copy, i),
- NULL,
- 0));
- }
- g_assert_not_reached();
- }
-
- /* also check equality using nm_ip6_config_replace() */
- g_assert(nm_ip6_config_replace(copy2, copy, NULL) == FALSE);
- }
-
- g_free(idx);
- g_object_unref(copy);
- g_object_unref(copy2);
-}
-
-static void
-test_nm_ip6_config_addresses_sort(void)
-{
- NMIP6Config *config = build_test_config();
-
-#define ADDR_ADD(...) \
- nm_ip6_config_add_address(config, nmtst_platform_ip6_address_full(__VA_ARGS__))
-
- nm_ip6_config_reset_addresses(config);
- ADDR_ADD("2607:f0d0:1002:51::4", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0);
- ADDR_ADD("2607:f0d0:1002:51::5", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0);
- ADDR_ADD("2607:f0d0:1002:51::6",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_NDISC,
- 0,
- 0,
- 0,
- IFA_F_MANAGETEMPADDR);
- ADDR_ADD("2607:f0d0:1002:51::3",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_USER,
- 0,
- 0,
- 0,
- IFA_F_SECONDARY);
- ADDR_ADD("2607:f0d0:1002:51::8",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_USER,
- 0,
- 0,
- 0,
- IFA_F_SECONDARY);
- ADDR_ADD("2607:f0d0:1002:51::0",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_KERNEL,
- 0,
- 0,
- 0,
- IFA_F_SECONDARY);
- ADDR_ADD("fec0::1", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0);
- ADDR_ADD("fe80::208:74ff:feda:625c", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0);
- ADDR_ADD("fe80::208:74ff:feda:625d", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0);
- ADDR_ADD("::1", NULL, 128, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0);
- ADDR_ADD("2607:f0d0:1002:51::2",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_USER,
- 0,
- 0,
- 0,
- IFA_F_TENTATIVE);
- test_nm_ip6_config_addresses_sort_check(config, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, 8);
- test_nm_ip6_config_addresses_sort_check(config, NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED, 8);
- test_nm_ip6_config_addresses_sort_check(config,
- NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR,
- 8);
-
- nm_ip6_config_reset_addresses(config);
- ADDR_ADD("2607:f0d0:1002:51::3",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_USER,
- 0,
- 0,
- 0,
- IFA_F_SECONDARY);
- ADDR_ADD("2607:f0d0:1002:51::4", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0);
- ADDR_ADD("2607:f0d0:1002:51::5", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0);
- ADDR_ADD("2607:f0d0:1002:51::8",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_USER,
- 0,
- 0,
- 0,
- IFA_F_SECONDARY);
- ADDR_ADD("2607:f0d0:1002:51::0",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_KERNEL,
- 0,
- 0,
- 0,
- IFA_F_SECONDARY);
- ADDR_ADD("2607:f0d0:1002:51::6",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_NDISC,
- 0,
- 0,
- 0,
- IFA_F_MANAGETEMPADDR);
- ADDR_ADD("fec0::1", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0);
- ADDR_ADD("fe80::208:74ff:feda:625c", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0);
- ADDR_ADD("fe80::208:74ff:feda:625d", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0);
- ADDR_ADD("::1", NULL, 128, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0);
- ADDR_ADD("2607:f0d0:1002:51::2",
- NULL,
- 64,
- 0,
- NM_IP_CONFIG_SOURCE_USER,
- 0,
- 0,
- 0,
- IFA_F_TENTATIVE);
- test_nm_ip6_config_addresses_sort_check(config,
- NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
- 8);
-
-#undef ADDR_ADD
- g_object_unref(config);
-}
-
-static void
-test_strip_search_trailing_dot(void)
-{
- NMIP6Config *config;
-
- config = nmtst_ip6_config_new(1);
-
- nm_ip6_config_add_search(config, ".");
- nm_ip6_config_add_search(config, "foo");
- nm_ip6_config_add_search(config, "bar.");
- nm_ip6_config_add_search(config, "baz.com");
- nm_ip6_config_add_search(config, "baz.com.");
- nm_ip6_config_add_search(config, "foobar..");
- nm_ip6_config_add_search(config, ".foobar");
- nm_ip6_config_add_search(config, "~.");
-
- g_assert_cmpuint(nm_ip6_config_get_num_searches(config), ==, 4);
- g_assert_cmpstr(nm_ip6_config_get_search(config, 0), ==, "foo");
- g_assert_cmpstr(nm_ip6_config_get_search(config, 1), ==, "bar");
- g_assert_cmpstr(nm_ip6_config_get_search(config, 2), ==, "baz.com");
- g_assert_cmpstr(nm_ip6_config_get_search(config, 3), ==, "~");
-
- g_object_unref(config);
-}
-
-/*****************************************************************************/
-
-static void
-test_replace(gconstpointer user_data)
-{
- nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = nm_dedup_multi_index_new();
- const int TEST_IDX = GPOINTER_TO_INT(user_data);
- const int IFINDEX = 1;
- gs_unref_object NMIP6Config *src_conf = NULL;
- gs_unref_object NMIP6Config *dst_conf = NULL;
- NMPlatformIP6Address * addr;
- NMPlatformIP6Address addrs[5] = {};
- guint addrs_n = 0;
- guint i;
-
- dst_conf = nm_ip6_config_new(multi_idx, IFINDEX);
- src_conf = nm_ip6_config_new(multi_idx, IFINDEX);
-
- switch (TEST_IDX) {
- case 1:
- addr = &addrs[addrs_n++];
- addr->ifindex = IFINDEX;
- addr->address = *nmtst_inet6_from_string("fe80::78ec:7a6d:602d:20f2");
- addr->plen = 64;
- addr->n_ifa_flags = IFA_F_PERMANENT;
- addr->addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
- break;
- case 2:
- addr = &addrs[addrs_n++];
- addr->ifindex = IFINDEX;
- addr->address = *nmtst_inet6_from_string("fe80::78ec:7a6d:602d:20f2");
- addr->plen = 64;
- addr->n_ifa_flags = IFA_F_PERMANENT;
- addr->addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
-
- addr = &addrs[addrs_n++];
- addr->ifindex = IFINDEX;
- addr->address = *nmtst_inet6_from_string("1::1");
- addr->plen = 64;
- addr->addr_source = NM_IP_CONFIG_SOURCE_USER;
-
- nm_ip6_config_add_address(dst_conf, addr);
- break;
- default:
- g_assert_not_reached();
- }
-
- g_assert(addrs_n < G_N_ELEMENTS(addrs));
-
- for (i = 0; i < addrs_n; i++)
- nm_ip6_config_add_address(src_conf, &addrs[i]);
-
- nm_ip6_config_replace(dst_conf, src_conf, NULL);
-
- for (i = 0; i < addrs_n; i++) {
- const NMPlatformIP6Address *a = _nmtst_ip6_config_get_address(dst_conf, i);
- const NMPlatformIP6Address *b = _nmtst_ip6_config_get_address(src_conf, i);
-
- g_assert(nm_platform_ip6_address_cmp(&addrs[i], a) == 0);
- g_assert(nm_platform_ip6_address_cmp(&addrs[i], b) == 0);
- }
- g_assert(addrs_n == nm_ip6_config_get_num_addresses(dst_conf));
- g_assert(addrs_n == nm_ip6_config_get_num_addresses(src_conf));
-}
-
-/*****************************************************************************/
-
-NMTST_DEFINE();
-
-int
-main(int argc, char **argv)
-{
- nmtst_init_with_logging(&argc, &argv, NULL, "ALL");
-
- g_test_add_func("/ip6-config/subtract", test_subtract);
- g_test_add_func("/ip6-config/compare-with-source", test_compare_with_source);
- g_test_add_func("/ip6-config/add-address-with-source", test_add_address_with_source);
- g_test_add_func("/ip6-config/add-route-with-source", test_add_route_with_source);
- g_test_add_func("/ip6-config/test_nm_ip6_config_addresses_sort",
- test_nm_ip6_config_addresses_sort);
- g_test_add_func("/ip6-config/strip-search-trailing-dot", test_strip_search_trailing_dot);
- g_test_add_data_func("/ip6-config/replace/1", GINT_TO_POINTER(1), test_replace);
- g_test_add_data_func("/ip6-config/replace/2", GINT_TO_POINTER(2), test_replace);
-
- return g_test_run();
-}
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
index d06ca46adc..ac64c1362a 100644
--- a/src/core/vpn/nm-vpn-connection.c
+++ b/src/core/vpn/nm-vpn-connection.c
@@ -17,9 +17,6 @@
#include <linux/if.h>
#include <linux/rtnetlink.h>
-#include "nm-proxy-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-active-connection.h"
#include "NetworkManagerUtils.h"
@@ -34,6 +31,7 @@
#include "nm-vpn-plugin-info.h"
#include "nm-vpn-manager.h"
#include "dns/nm-dns-manager.h"
+#include "nm-l3-config-data.h"
typedef enum {
/* Only system secrets */
@@ -100,26 +98,25 @@ typedef struct {
NMNetns *netns;
- GPtrArray *ip4_dev_route_blacklist;
+ NML3Cfg *l3cfg;
GDBusProxy * proxy;
GCancellable * cancellable;
GVariant * connect_hash;
guint connect_timeout;
- NMProxyConfig * proxy_config;
NMPacrunnerConfId *pacrunner_conf_id;
gboolean has_ip4;
- NMIP4Config * ip4_config;
- guint32 ip4_internal_gw;
- guint32 ip4_external_gw;
- gboolean has_ip6;
- NMIP6Config * ip6_config;
-
- /* These config instances are passed on to NMDevice and modified by NMDevice.
- * This pointer is only useful for nm_device_replace_vpn4_config() to clear the
- * previous configuration. Consider these instances to be owned by NMDevice. */
- NMIP4Config *last_device_ip4_config;
- NMIP6Config *last_device_ip6_config;
+
+ union {
+ struct {
+ const NML3ConfigData *l3cd_6;
+ const NML3ConfigData *l3cd_4;
+ };
+ const NML3ConfigData *l3cd_x[2];
+ };
+ guint32 ip4_internal_gw;
+ guint32 ip4_external_gw;
+ gboolean has_ip6;
struct in6_addr *ip6_internal_gw;
struct in6_addr *ip6_external_gw;
@@ -351,6 +348,8 @@ fw_call_cleanup(NMVpnConnection *self)
static void
remove_parent_device_config(NMVpnConnection *connection, NMDevice *device)
{
+ /* FIXME(l3cfg) */
+#if 0
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(connection);
if (priv->last_device_ip4_config) {
@@ -362,6 +361,7 @@ remove_parent_device_config(NMVpnConnection *connection, NMDevice *device)
nm_device_replace_vpn6_config(device, priv->last_device_ip6_config, NULL);
g_clear_object(&priv->last_device_ip6_config);
}
+#endif
}
static void
@@ -514,9 +514,7 @@ _set_vpn_state(NMVpnConnection * self,
_get_applied_connection(self),
parent_dev,
priv->ip_iface,
- priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config,
+ NULL, //XXX
dispatcher_pre_up_done,
self,
&priv->dispatcher_id)) {
@@ -536,21 +534,19 @@ _set_vpn_state(NMVpnConnection * self,
applied,
parent_dev,
priv->ip_iface,
- priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config,
+ NULL, //XXX
NULL,
NULL,
NULL);
- if (priv->proxy_config) {
- nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id);
- priv->pacrunner_conf_id = nm_pacrunner_manager_add(nm_pacrunner_manager_get(),
- priv->proxy_config,
- priv->ip_iface,
- priv->ip4_config,
- priv->ip6_config);
- }
+ //XXX if (priv->proxy_config) {
+ //XXX nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id);
+ //XXX priv->pacrunner_conf_id = nm_pacrunner_manager_add(nm_pacrunner_manager_get(),
+ //XXX priv->proxy_config,
+ //XXX priv->ip_iface,
+ //XXX priv->ip4_config,
+ //XXX priv->ip6_config);
+ //XXX }
break;
case STATE_DEACTIVATING:
applied = _get_applied_connection(self);
@@ -560,18 +556,15 @@ _set_vpn_state(NMVpnConnection * self,
applied,
parent_dev,
priv->ip_iface,
- priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config);
+ NULL //XXX
+ );
} else {
if (!nm_dispatcher_call_vpn(NM_DISPATCHER_ACTION_VPN_PRE_DOWN,
_get_settings_connection(self, FALSE),
applied,
parent_dev,
priv->ip_iface,
- priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config,
+ NULL, //XXX
dispatcher_pre_down_done,
self,
&priv->dispatcher_id)) {
@@ -592,8 +585,6 @@ _set_vpn_state(NMVpnConnection * self,
_get_applied_connection(self),
parent_dev,
priv->ip_iface,
- NULL,
- NULL,
NULL);
} else {
nm_dispatcher_call_vpn(NM_DISPATCHER_ACTION_VPN_DOWN,
@@ -604,8 +595,6 @@ _set_vpn_state(NMVpnConnection * self,
NULL,
NULL,
NULL,
- NULL,
- NULL,
NULL);
}
}
@@ -678,11 +667,12 @@ device_state_changed(NMActiveConnection *active,
*/
}
-static void
-add_ip4_vpn_gateway_route(NMIP4Config *config,
- NMDevice * parent_device,
- in_addr_t vpn_gw,
- NMPlatform * platform)
+//XXX
+_nm_unused static void
+add_ip4_vpn_gateway_route(NML3ConfigData *l3cd,
+ NMDevice * parent_device,
+ in_addr_t vpn_gw,
+ NMPlatform * platform)
{
guint32 parent_gw = 0;
gboolean has_parent_gw = FALSE;
@@ -691,11 +681,11 @@ add_ip4_vpn_gateway_route(NMIP4Config *config,
guint32 route_metric;
nm_auto_nmpobj const NMPObject *route_resolved = NULL;
- g_return_if_fail(NM_IS_IP4_CONFIG(config));
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
g_return_if_fail(NM_IS_DEVICE(parent_device));
g_return_if_fail(vpn_gw != 0);
- ifindex = nm_ip4_config_get_ifindex(config);
+ ifindex = nm_l3_config_data_get_ifindex(l3cd);
nm_assert(ifindex > 0);
nm_assert(ifindex == nm_device_get_ip_ifindex(parent_device));
@@ -737,14 +727,15 @@ add_ip4_vpn_gateway_route(NMIP4Config *config,
route_metric = nm_device_get_route_metric(parent_device, AF_INET);
- memset(&route, 0, sizeof(route));
- route.ifindex = ifindex;
- route.network = vpn_gw;
- route.plen = 32;
- route.gateway = parent_gw;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- route.metric = route_metric;
- nm_ip4_config_add_route(config, &route, NULL);
+ route = (NMPlatformIP4Route){
+ .ifindex = ifindex,
+ .network = vpn_gw,
+ .plen = 32,
+ .gateway = parent_gw,
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ .metric = route_metric,
+ };
+ nm_l3_config_data_add_route_4(l3cd, &route);
if (parent_gw) {
/* Ensure there's a route to the parent device's gateway through the
@@ -752,17 +743,19 @@ add_ip4_vpn_gateway_route(NMIP4Config *config,
* routes include a subnet that matches the parent device's subnet,
* the parent device's gateway would get routed through the VPN and fail.
*/
- memset(&route, 0, sizeof(route));
- route.network = parent_gw;
- route.plen = 32;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- route.metric = route_metric;
- nm_ip4_config_add_route(config, &route, NULL);
+ route = (NMPlatformIP4Route){
+ .network = parent_gw,
+ .plen = 32,
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ .metric = route_metric,
+ };
+ nm_l3_config_data_add_route_4(l3cd, &route);
}
}
-static void
-add_ip6_vpn_gateway_route(NMIP6Config * config,
+//XXX
+_nm_unused static void
+add_ip6_vpn_gateway_route(NML3ConfigData * l3cd,
NMDevice * parent_device,
const struct in6_addr *vpn_gw,
NMPlatform * platform)
@@ -774,11 +767,11 @@ add_ip6_vpn_gateway_route(NMIP6Config * config,
guint32 route_metric;
nm_auto_nmpobj const NMPObject *route_resolved = NULL;
- g_return_if_fail(NM_IS_IP6_CONFIG(config));
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
g_return_if_fail(NM_IS_DEVICE(parent_device));
g_return_if_fail(vpn_gw != NULL);
- ifindex = nm_ip6_config_get_ifindex(config);
+ ifindex = nm_l3_config_data_get_ifindex(l3cd);
nm_assert(ifindex > 0);
nm_assert(ifindex == nm_device_get_ip_ifindex(parent_device));
@@ -820,15 +813,15 @@ add_ip6_vpn_gateway_route(NMIP6Config * config,
route_metric = nm_device_get_route_metric(parent_device, AF_INET6);
- memset(&route, 0, sizeof(route));
- route.ifindex = ifindex;
- route.network = *vpn_gw;
- route.plen = 128;
- if (parent_gw)
- route.gateway = *parent_gw;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- route.metric = route_metric;
- nm_ip6_config_add_route(config, &route, NULL);
+ route = (NMPlatformIP6Route){
+ .ifindex = ifindex,
+ .network = *vpn_gw,
+ .plen = 128,
+ .gateway = (parent_gw ? *parent_gw : in6addr_any),
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ .metric = route_metric,
+ };
+ nm_l3_config_data_add_route_6(l3cd, &route);
/* Ensure there's a route to the parent device's gateway through the
* parent device, since if the VPN claims the default route and the VPN
@@ -836,12 +829,13 @@ add_ip6_vpn_gateway_route(NMIP6Config * config,
* the parent device's gateway would get routed through the VPN and fail.
*/
if (parent_gw && !IN6_IS_ADDR_UNSPECIFIED(parent_gw)) {
- memset(&route, 0, sizeof(route));
- route.network = *parent_gw;
- route.plen = 128;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- route.metric = route_metric;
- nm_ip6_config_add_route(config, &route, NULL);
+ route = (NMPlatformIP6Route){
+ .network = *parent_gw,
+ .plen = 128,
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ .metric = route_metric,
+ };
+ nm_l3_config_data_add_route_6(l3cd, &route);
}
}
@@ -988,14 +982,13 @@ plugin_state_changed(NMVpnConnection *self, NMVpnServiceState new_service_state)
static void
print_vpn_config(NMVpnConnection *self)
{
- NMVpnConnectionPrivate * priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
- const NMPlatformIP4Address *address4;
- const NMPlatformIP6Address *address6;
- char * dns_domain = NULL;
- guint32 num, i;
- char b1[NM_UTILS_INET_ADDRSTRLEN];
- char b2[NM_UTILS_INET_ADDRSTRLEN];
- NMDedupMultiIter ipconf_iter;
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
+ const char *const * strv;
+ guint num;
+ guint i;
+ char b1[NM_UTILS_INET_ADDRSTRLEN];
+ char sbuf1[sizeof(_nm_utils_to_string_buffer)];
+ NMDedupMultiIter ipconf_iter;
if (priv->ip4_external_gw) {
_LOGI("Data: VPN Gateway: %s", _nm_utils_inet4_ntop(priv->ip4_external_gw, b1));
@@ -1005,78 +998,57 @@ print_vpn_config(NMVpnConnection *self)
_LOGI("Data: Tunnel Device: %s%s%s", NM_PRINT_FMT_QUOTE_STRING(priv->ip_iface));
- if (priv->ip4_config) {
- const NMPlatformIP4Route *route;
-
- _LOGI("Data: IPv4 configuration:");
+ for (i = 0; i < 2; i++) {
+ const gboolean IS_IPv4 = (i == 0);
+ const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
+ const NML3ConfigData *l3cd = priv->l3cd_x[IS_IPv4];
+ const NMPObject * plobj;
+ const guint8 * p_addrs;
- address4 = nm_ip4_config_get_first_address(priv->ip4_config);
- nm_assert(address4);
+ if (!l3cd) {
+ _LOGI("Data: No IPv%c configuration", nm_utils_addr_family_to_char(addr_family));
+ continue;
+ }
- if (priv->ip4_internal_gw)
- _LOGI("Data: Internal Gateway: %s", _nm_utils_inet4_ntop(priv->ip4_internal_gw, b1));
- _LOGI("Data: Internal Address: %s",
- address4 ? _nm_utils_inet4_ntop(address4->address, b1) : "??");
- _LOGI("Data: Internal Prefix: %d", address4 ? (int) address4->plen : -1);
- _LOGI("Data: Internal Point-to-Point Address: %s",
- _nm_utils_inet4_ntop(address4->peer_address, b1));
+ _LOGI("Data: IPv%c configuration:", nm_utils_addr_family_to_char(addr_family));
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, priv->ip4_config, &route) {
- _LOGI("Data: Static Route: %s/%d Next Hop: %s",
- _nm_utils_inet4_ntop(route->network, b1),
- route->plen,
- _nm_utils_inet4_ntop(route->gateway, b2));
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &plobj,
+ NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) {
+ _LOGI("Data: Internal Address: %s",
+ nmp_object_to_string(plobj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof(sbuf1)));
}
- num = nm_ip4_config_get_num_nameservers(priv->ip4_config);
- for (i = 0; i < num; i++) {
- _LOGI("Data: Internal DNS: %s",
- _nm_utils_inet4_ntop(nm_ip4_config_get_nameserver(priv->ip4_config, i), b1));
+ if (IS_IPv4) {
+ if (priv->ip4_internal_gw)
+ _LOGI("Data: Internal Gateway: %s",
+ _nm_utils_inet4_ntop(priv->ip4_internal_gw, b1));
+ } else {
+ if (priv->ip6_internal_gw)
+ _LOGI("Data: Internal Gateway: %s",
+ _nm_utils_inet6_ntop(priv->ip6_internal_gw, b1));
}
- if (nm_ip4_config_get_num_domains(priv->ip4_config) > 0)
- dns_domain = (char *) nm_ip4_config_get_domain(priv->ip4_config, 0);
-
- _LOGI("Data: DNS Domain: '%s'", dns_domain ?: "(none)");
- } else
- _LOGI("Data: No IPv4 configuration");
-
- if (priv->ip6_config) {
- const NMPlatformIP6Route *route;
-
- _LOGI("Data: IPv6 configuration:");
-
- address6 = nm_ip6_config_get_first_address(priv->ip6_config);
- nm_assert(address6);
-
- if (priv->ip6_internal_gw)
- _LOGI("Data: Internal Gateway: %s", _nm_utils_inet6_ntop(priv->ip6_internal_gw, b1));
- _LOGI("Data: Internal Address: %s", _nm_utils_inet6_ntop(&address6->address, b1));
- _LOGI("Data: Internal Prefix: %d", address6->plen);
- _LOGI("Data: Internal Point-to-Point Address: %s",
- _nm_utils_inet6_ntop(&address6->peer_address, b1));
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, priv->ip6_config, &route) {
- _LOGI("Data: Static Route: %s/%d Next Hop: %s",
- _nm_utils_inet6_ntop(&route->network, b1),
- route->plen,
- _nm_utils_inet6_ntop(&route->gateway, b2));
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &plobj,
+ NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) {
+ _LOGI("Data: Static Route: %s",
+ nmp_object_to_string(plobj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof(sbuf1)));
}
- num = nm_ip6_config_get_num_nameservers(priv->ip6_config);
- for (i = 0; i < num; i++) {
- _LOGI("Data: Internal DNS: %s",
- _nm_utils_inet6_ntop(nm_ip6_config_get_nameserver(priv->ip6_config, i), b1));
+ p_addrs = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num);
+ for (i = 0; i < num; i++, p_addrs += nm_utils_addr_family_to_size(addr_family)) {
+ _LOGI("Data: Internal DNS: %s", nm_utils_inet_ntop(addr_family, p_addrs, b1));
}
- if (nm_ip6_config_get_num_domains(priv->ip6_config) > 0)
- dns_domain = (char *) nm_ip6_config_get_domain(priv->ip6_config, 0);
-
- _LOGI("Data: DNS Domain: '%s'", dns_domain ?: "(none)");
- } else
- _LOGI("Data: No IPv6 configuration");
+ strv = nm_l3_config_data_get_domains(l3cd, addr_family, &num);
+ for (i = 0; i < num; i++)
+ _LOGI("Data: DNS Domain: '%s'", strv[i]);
+ }
- if (priv->banner && strlen(priv->banner)) {
+ if (!nm_str_is_empty(priv->banner)) {
_LOGI("Data: Login Banner:");
_LOGI("Data: -----------------------------------------");
_LOGI("Data: %s", priv->banner);
@@ -1087,62 +1059,63 @@ print_vpn_config(NMVpnConnection *self)
static void
apply_parent_device_config(NMVpnConnection *self)
{
- NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
- NMDevice * parent_dev = nm_active_connection_get_device(NM_ACTIVE_CONNECTION(self));
- int ifindex;
- NMIP4Config *vpn4_parent_config = NULL;
- NMIP6Config *vpn6_parent_config = NULL;
+#if 0
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
+ NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (self));
+ int ifindex;
+ NMIP4Config *vpn4_parent_config = NULL;
+ NMIP6Config *vpn6_parent_config = NULL;
- ifindex = nm_device_get_ip_ifindex(parent_dev);
- if (ifindex > 0) {
- /* If the VPN didn't return a network interface, it is a route-based
+ ifindex = nm_device_get_ip_ifindex (parent_dev);
+ if (ifindex > 0) {
+ /* If the VPN didn't return a network interface, it is a route-based
* VPN (like kernel IPSec) and all IP addressing and routing should
* be done on the parent interface instead.
*/
- if (priv->ip4_config) {
- vpn4_parent_config = nm_ip4_config_new(nm_netns_get_multi_idx(priv->netns), ifindex);
- if (priv->ip_ifindex <= 0)
- nm_ip4_config_merge(vpn4_parent_config,
- priv->ip4_config,
- NM_IP_CONFIG_MERGE_NO_DNS,
- 0);
- }
- if (priv->ip6_config) {
- vpn6_parent_config = nm_ip6_config_new(nm_netns_get_multi_idx(priv->netns), ifindex);
- if (priv->ip_ifindex <= 0)
- nm_ip6_config_merge(vpn6_parent_config,
- priv->ip6_config,
- NM_IP_CONFIG_MERGE_NO_DNS,
- 0);
- }
- }
-
- /* Add any explicit route to the VPN gateway through the parent device */
- if (vpn4_parent_config && priv->ip4_external_gw) {
- add_ip4_vpn_gateway_route(vpn4_parent_config,
- parent_dev,
- priv->ip4_external_gw,
- nm_netns_get_platform(priv->netns));
- }
- if (vpn6_parent_config && priv->ip6_external_gw) {
- add_ip6_vpn_gateway_route(vpn6_parent_config,
- parent_dev,
- priv->ip6_external_gw,
- nm_netns_get_platform(priv->netns));
- }
-
- nm_device_replace_vpn4_config(parent_dev, priv->last_device_ip4_config, vpn4_parent_config);
- g_clear_object(&priv->last_device_ip4_config);
- priv->last_device_ip4_config = vpn4_parent_config;
-
- nm_device_replace_vpn6_config(parent_dev, priv->last_device_ip6_config, vpn6_parent_config);
- g_clear_object(&priv->last_device_ip6_config);
- priv->last_device_ip6_config = vpn6_parent_config;
+ if (priv->ip4_config) {
+ vpn4_parent_config = nm_ip4_config_new (nm_netns_get_multi_idx (priv->netns),
+ ifindex);
+ if (priv->ip_ifindex <= 0)
+ nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_NO_DNS, 0);
+ }
+ if (priv->ip6_config) {
+ vpn6_parent_config = nm_ip6_config_new (nm_netns_get_multi_idx (priv->netns),
+ ifindex);
+ if (priv->ip_ifindex <= 0)
+ nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_NO_DNS, 0);
+ }
+ }
+
+ /* Add any explicit route to the VPN gateway through the parent device */
+ if ( vpn4_parent_config
+ && priv->ip4_external_gw) {
+ add_ip4_vpn_gateway_route (vpn4_parent_config,
+ parent_dev,
+ priv->ip4_external_gw,
+ nm_netns_get_platform (priv->netns));
+ }
+ if ( vpn6_parent_config
+ && priv->ip6_external_gw) {
+ add_ip6_vpn_gateway_route (vpn6_parent_config,
+ parent_dev,
+ priv->ip6_external_gw,
+ nm_netns_get_platform (priv->netns));
+ }
+
+ nm_device_replace_vpn4_config (parent_dev, priv->last_device_ip4_config, vpn4_parent_config);
+ g_clear_object (&priv->last_device_ip4_config);
+ priv->last_device_ip4_config = vpn4_parent_config;
+
+ nm_device_replace_vpn6_config (parent_dev, priv->last_device_ip6_config, vpn6_parent_config);
+ g_clear_object (&priv->last_device_ip6_config);
+ priv->last_device_ip6_config = vpn6_parent_config;
+#endif
}
static gboolean
nm_vpn_connection_apply_config(NMVpnConnection *self)
{
+#if 0
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
apply_parent_device_config(self);
@@ -1189,16 +1162,15 @@ nm_vpn_connection_apply_config(NMVpnConnection *self)
_LOGI("VPN connection: (IP Config Get) complete");
if (priv->vpn_state < STATE_PRE_UP)
_set_vpn_state(self, STATE_PRE_UP, NM_ACTIVE_CONNECTION_STATE_REASON_NONE, FALSE);
+#endif
return TRUE;
}
static void
_cleanup_failed_config(NMVpnConnection *self)
{
- NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
-
- nm_dbus_object_clear_and_unexport(&priv->ip4_config);
- nm_dbus_object_clear_and_unexport(&priv->ip6_config);
+ //XXX nm_dbus_object_clear_and_unexport(&priv->ip4_config);
+ //XXX nm_dbus_object_clear_and_unexport(&priv->ip6_config);
_LOGW("VPN connection: did not receive valid IP config information");
_set_vpn_state(self, STATE_FAILED, NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, FALSE);
@@ -1243,10 +1215,10 @@ nm_vpn_connection_config_maybe_complete(NMVpnConnection *self, gboolean success)
return;
if (success) {
- if ((priv->has_ip4 && !priv->ip4_config) || (priv->has_ip6 && !priv->ip6_config)) {
- /* Need to wait for other config */
- return;
- }
+ //XXX if ((priv->has_ip4 && !priv->ip4_config) || (priv->has_ip6 && !priv->ip6_config)) {
+ //XXX /* Need to wait for other config */
+ //XXX return;
+ //XXX }
}
nm_clear_g_source(&priv->connect_timeout);
@@ -1286,26 +1258,23 @@ ip6_addr_from_variant(GVariant *v, struct in6_addr *addr)
g_return_val_if_fail(v, FALSE);
g_return_val_if_fail(addr, FALSE);
+ nm_assert(g_variant_is_of_type(v, G_VARIANT_TYPE("ay")));
- if (g_variant_is_of_type(v, G_VARIANT_TYPE("ay"))) {
- bytes = g_variant_get_fixed_array(v, &len, sizeof(guint8));
- if (len == sizeof(struct in6_addr) && !IN6_IS_ADDR_UNSPECIFIED(bytes)) {
- memcpy(addr, bytes, len);
- return TRUE;
- }
+ bytes = g_variant_get_fixed_array(v, &len, sizeof(guint8));
+ if (len == sizeof(struct in6_addr) && !IN6_IS_ADDR_UNSPECIFIED(bytes)) {
+ memcpy(addr, bytes, len);
+ return TRUE;
}
return FALSE;
}
static struct in6_addr *
-ip6_addr_dup_from_variant(GVariant *v)
+ip6_addr_from_variant_dup(GVariant *v)
{
- struct in6_addr *addr;
+ struct in6_addr addr;
- addr = g_malloc0(sizeof(*addr));
- if (ip6_addr_from_variant(v, addr))
- return addr;
- g_free(addr);
+ if (ip6_addr_from_variant(v, &addr))
+ return nm_memdup(&addr, sizeof(addr));
return NULL;
}
@@ -1356,19 +1325,15 @@ process_generic_config(NMVpnConnection *self, GVariant *dict)
_notify(self, PROP_BANNER);
}
- /* Proxy Config */
- g_clear_object(&priv->proxy_config);
- priv->proxy_config = nm_proxy_config_new();
-
- if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_PROXY_PAC, "&s", &str)) {
- nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO);
- nm_proxy_config_set_pac_url(priv->proxy_config, str);
- } else
- nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE);
+ //XXX if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_PROXY_PAC, "&s", &str)) {
+ //XXX nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO);
+ //XXX nm_proxy_config_set_pac_url(priv->proxy_config, str);
+ //XXX } else
+ //XXX nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE);
- /* User overrides if any from the NMConnection's Proxy settings */
- nm_proxy_config_merge_setting(priv->proxy_config,
- nm_connection_get_setting_proxy(_get_applied_connection(self)));
+ //XXX /* User overrides if any from the NMConnection's Proxy settings */
+ //XXX nm_proxy_config_merge_setting(priv->proxy_config,
+ //XXX nm_connection_get_setting_proxy(_get_applied_connection(self)));
/* External world-visible address of the VPN server */
priv->ip4_external_gw = 0;
@@ -1377,7 +1342,7 @@ process_generic_config(NMVpnConnection *self, GVariant *dict)
if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY, "u", &u32)) {
priv->ip4_external_gw = u32;
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY, "@ay", &v)) {
- priv->ip6_external_gw = ip6_addr_dup_from_variant(v);
+ priv->ip6_external_gw = ip6_addr_from_variant_dup(v);
g_variant_unref(v);
if (!priv->ip6_external_gw) {
@@ -1414,12 +1379,12 @@ nm_vpn_connection_config_get(NMVpnConnection *self, GVariant *dict)
priv->has_ip4 = FALSE;
if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_HAS_IP4, "b", &b))
priv->has_ip4 = b;
- nm_dbus_object_clear_and_unexport(&priv->ip4_config);
+ //XXX nm_dbus_object_clear_and_unexport(&priv->ip4_config);
priv->has_ip6 = FALSE;
if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_HAS_IP6, "b", &b))
priv->has_ip6 = b;
- nm_dbus_object_clear_and_unexport(&priv->ip6_config);
+ //XXX nm_dbus_object_clear_and_unexport(&priv->ip6_config);
nm_vpn_connection_config_maybe_complete(self, TRUE);
}
@@ -1469,7 +1434,8 @@ get_route_table(NMVpnConnection *self, int addr_family, gboolean fallback_main)
return route_table ?: (fallback_main ? RT_TABLE_MAIN : 0);
}
-static gboolean
+//XXX
+_nm_unused static gboolean
_is_device_vrf(NMVpnConnection *self)
{
NMDevice *parent;
@@ -1486,20 +1452,20 @@ _is_device_vrf(NMVpnConnection *self)
static void
nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
{
- NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
- NMPlatformIP4Address address;
- guint32 u32, route_metric;
- NMSettingIPConfig * s_ip;
- NMSettingConnection * s_con;
- guint32 route_table;
- NMIP4Config * config;
- GVariantIter * iter;
- const char * str;
- GVariant * v;
- gboolean b;
- int ip_ifindex;
- guint32 mss = 0;
- gboolean never_default = FALSE;
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP4Address address;
+ guint32 u32, route_metric;
+ NMSettingIPConfig * s_ip;
+ NMSettingConnection * s_con;
+ guint32 route_table;
+ GVariantIter * iter;
+ const char * str;
+ GVariant * v;
+ gboolean b;
+ int ip_ifindex;
+ guint32 mss = 0;
+ gboolean never_default = FALSE;
g_return_if_fail(dict && g_variant_is_of_type(dict, G_VARIANT_TYPE_VARDICT));
@@ -1536,11 +1502,15 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
if (ip_ifindex <= 0)
g_return_if_reached();
- config = nm_ip4_config_new(nm_netns_get_multi_idx(priv->netns), ip_ifindex);
- nm_ip4_config_set_dns_priority(config, NM_DNS_PRIORITY_DEFAULT_VPN);
+ l3cd = nm_l3_config_data_new(nm_netns_get_multi_idx(priv->netns),
+ ip_ifindex,
+ NM_IP_CONFIG_SOURCE_VPN);
- memset(&address, 0, sizeof(address));
- address.plen = 24;
+ nm_l3_config_data_set_dns_priority(l3cd, AF_INET, NM_DNS_PRIORITY_DEFAULT_VPN);
+
+ address = (NMPlatformIP4Address){
+ .plen = 24,
+ };
/* Internal address of the VPN subnet's gateway */
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY, "u", &u32))
@@ -1559,23 +1529,22 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
if (address.address && address.plen && address.plen <= 32) {
address.addr_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip4_config_add_address(config, &address);
+ nm_l3_config_data_add_address_4(l3cd, &address);
} else {
_LOGW("invalid IP4 config received!");
- g_object_unref(config);
nm_vpn_connection_config_maybe_complete(self, FALSE);
return;
}
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_DNS, "au", &iter)) {
while (g_variant_iter_next(iter, "u", &u32))
- nm_ip4_config_add_nameserver(config, u32);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &u32);
g_variant_iter_free(iter);
}
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, "au", &iter)) {
while (g_variant_iter_next(iter, "u", &u32))
- nm_ip4_config_add_wins(config, u32);
+ nm_l3_config_data_add_wins(l3cd, u32);
g_variant_iter_free(iter);
}
@@ -1583,11 +1552,11 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
mss = u32;
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN, "&s", &str))
- nm_ip4_config_add_domain(config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, str);
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_DOMAINS, "as", &iter)) {
while (g_variant_iter_next(iter, "&s", &str))
- nm_ip4_config_add_domain(config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, str);
g_variant_iter_free(iter);
}
@@ -1599,12 +1568,12 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
if (nm_setting_ip_config_get_ignore_auto_routes(s_ip)) {
/* ignore VPN routes */
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_PRESERVE_ROUTES, "b", &b) && b) {
- if (priv->ip4_config) {
- NMDedupMultiIter ipconf_iter;
+ if (priv->l3cd_4) {
const NMPlatformIP4Route *route;
+ NMDedupMultiIter ipconf_iter;
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, priv->ip4_config, &route)
- nm_ip4_config_add_route(config, route, NULL);
+ nm_l3_config_data_iter_ip4_route_for_each (&ipconf_iter, priv->l3cd_4, &route)
+ nm_l3_config_data_add_route_4(l3cd, route);
}
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_ROUTES, "aau", &iter)) {
while (g_variant_iter_next(iter, "@au", &v)) {
@@ -1641,7 +1610,7 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
break;
}
- nm_ip4_config_add_route(config, &route, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &route);
break;
default:
break;
@@ -1655,12 +1624,14 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
never_default = b;
/* Merge in user overrides from the NMConnection's IPv4 setting */
- nm_ip4_config_merge_setting(config,
- s_ip,
- nm_setting_connection_get_mdns(s_con),
- nm_setting_connection_get_llmnr(s_con),
- route_table,
- route_metric);
+ (void) s_con;
+ //XXX
+ //nm_ip4_config_merge_setting (config,
+ // s_ip,
+ // nm_setting_connection_get_mdns (s_con),
+ // nm_setting_connection_get_llmnr (s_con),
+ // route_table,
+ // route_metric);
if (!never_default && !nm_setting_ip_config_get_never_default(s_ip)) {
const NMPlatformIP4Route r = {
@@ -1672,45 +1643,47 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
.mss = mss,
};
- nm_ip4_config_add_route(config, &r, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &r);
}
- nm_clear_pointer(&priv->ip4_dev_route_blacklist, g_ptr_array_unref);
+ //XXX nm_l3_config_data_add_dependent_routes(l3cd,
+ //XXX AF_INET,
+ //XXX route_table,
+ //XXX nm_vpn_connection_get_ip4_route_metric(self),
+ //XXX _is_device_vrf(self));
- nm_ip4_config_add_dependent_routes(config,
- route_table,
- nm_vpn_connection_get_ip4_route_metric(self),
- _is_device_vrf(self),
- &priv->ip4_dev_route_blacklist);
+ //XXX
+#if 0
+ if (priv->ip4_config) {
+ nm_ip4_config_replace (priv->ip4_config, config, NULL);
+ g_object_unref (config);
+ } else {
+ priv->ip4_config = config;
+ nm_dbus_object_export (NM_DBUS_OBJECT (config));
+ g_object_notify ((GObject *) self, NM_ACTIVE_CONNECTION_IP4_CONFIG);
+ }
- if (priv->ip4_config) {
- nm_ip4_config_replace(priv->ip4_config, config, NULL);
- g_object_unref(config);
- } else {
- priv->ip4_config = config;
- nm_dbus_object_export(NM_DBUS_OBJECT(config));
- g_object_notify((GObject *) self, NM_ACTIVE_CONNECTION_IP4_CONFIG);
- }
-
- nm_vpn_connection_config_maybe_complete(self, TRUE);
+ nm_vpn_connection_config_maybe_complete (self, TRUE);
+#endif
}
static void
nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
{
- NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
- NMPlatformIP6Address address;
- guint32 u32, route_metric;
- NMSettingIPConfig * s_ip;
- guint32 route_table;
- NMIP6Config * config;
- GVariantIter * iter;
- const char * str;
- GVariant * v;
- gboolean b;
- int ip_ifindex;
- guint32 mss = 0;
- gboolean never_default = FALSE;
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP6Address address;
+ guint32 u32;
+ guint32 route_metric;
+ NMSettingIPConfig * s_ip;
+ guint32 route_table;
+ GVariantIter * iter;
+ const char * str;
+ GVariant * v;
+ gboolean b;
+ int ip_ifindex;
+ guint32 mss = 0;
+ gboolean never_default = FALSE;
g_return_if_fail(dict && g_variant_is_of_type(dict, G_VARIANT_TYPE_VARDICT));
@@ -1734,16 +1707,20 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
if (ip_ifindex <= 0)
g_return_if_reached();
- config = nm_ip6_config_new(nm_netns_get_multi_idx(priv->netns), ip_ifindex);
- nm_ip6_config_set_dns_priority(config, NM_DNS_PRIORITY_DEFAULT_VPN);
+ l3cd = nm_l3_config_data_new(nm_netns_get_multi_idx(priv->netns),
+ ip_ifindex,
+ NM_IP_CONFIG_SOURCE_VPN);
+
+ nm_l3_config_data_set_dns_priority(l3cd, AF_INET6, NM_DNS_PRIORITY_DEFAULT_VPN);
- memset(&address, 0, sizeof(address));
- address.plen = 128;
+ address = (NMPlatformIP6Address){
+ .plen = 128,
+ };
/* Internal address of the VPN subnet's gateway */
nm_clear_g_free(&priv->ip6_internal_gw);
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY, "@ay", &v)) {
- priv->ip6_internal_gw = ip6_addr_dup_from_variant(v);
+ priv->ip6_internal_gw = ip6_addr_from_variant_dup(v);
g_variant_unref(v);
}
@@ -1762,10 +1739,9 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
if (!IN6_IS_ADDR_UNSPECIFIED(&address.address) && address.plen && address.plen <= 128) {
address.addr_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip6_config_add_address(config, &address);
+ nm_l3_config_data_add_address_6(l3cd, &address);
} else {
_LOGW("invalid IP6 config received!");
- g_object_unref(config);
nm_vpn_connection_config_maybe_complete(self, FALSE);
return;
}
@@ -1775,7 +1751,7 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
struct in6_addr dns;
if (ip6_addr_from_variant(v, &dns))
- nm_ip6_config_add_nameserver(config, &dns);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &dns);
g_variant_unref(v);
}
g_variant_iter_free(iter);
@@ -1785,11 +1761,11 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
mss = u32;
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_DOMAIN, "&s", &str))
- nm_ip6_config_add_domain(config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET6, str);
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS, "as", &iter)) {
while (g_variant_iter_next(iter, "&s", &str))
- nm_ip6_config_add_domain(config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET6, str);
g_variant_iter_free(iter);
}
@@ -1800,33 +1776,41 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
if (nm_setting_ip_config_get_ignore_auto_routes(s_ip)) {
/* Ignore VPN routes */
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_PRESERVE_ROUTES, "b", &b) && b) {
- if (priv->ip6_config) {
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Route *route;
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, priv->ip6_config, &route)
- nm_ip6_config_add_route(config, route, NULL);
+ if (priv->l3cd_6) {
+ NMDedupMultiIter ipconf_iter;
+ const NMPObject *route;
+
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ priv->l3cd_6,
+ &route,
+ NMP_OBJECT_TYPE_IP6_ROUTE)
+ nm_l3_config_data_add_route(l3cd, AF_INET6, route, NULL);
}
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_ROUTES, "a(ayuayu)", &iter)) {
- GVariant *dest, *next_hop;
- guint32 prefix, metric;
+ GVariant *next_hop;
+ GVariant *dest;
+ guint32 prefix;
+ guint32 metric;
while (g_variant_iter_next(iter, "(@ayu@ayu)", &dest, &prefix, &next_hop, &metric)) {
- NMPlatformIP6Route route;
+ _nm_unused gs_unref_variant GVariant *nexT_hop_keep_alive = next_hop;
+ _nm_unused gs_unref_variant GVariant *dest_keep_alive = dest;
+ NMPlatformIP6Route route;
- memset(&route, 0, sizeof(route));
+ if (prefix > 128)
+ continue;
- if (!ip6_addr_from_variant(dest, &route.network))
- goto next;
+ route = (NMPlatformIP6Route){
+ .plen = prefix,
+ .table_coerced = nm_platform_route_table_coerce(route_table),
+ .metric = route_metric,
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ };
- if (prefix > 128)
- goto next;
+ if (!ip6_addr_from_variant(dest, &route.network))
+ continue;
- route.plen = prefix;
ip6_addr_from_variant(next_hop, &route.gateway);
- route.table_coerced = nm_platform_route_table_coerce(route_table);
- route.metric = route_metric;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
nm_utils_ip6_address_clear_host_address(&route.network, &route.network, route.plen);
@@ -1837,14 +1821,10 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
* server, we want to use the NM created route instead of whatever
* the server provides.
*/
- goto next;
+ continue;
}
- nm_ip6_config_add_route(config, &route, NULL);
-
-next:
- g_variant_unref(dest);
- g_variant_unref(next_hop);
+ nm_l3_config_data_add_route_6(l3cd, &route);
}
g_variant_iter_free(iter);
}
@@ -1853,7 +1833,12 @@ next:
never_default = b;
/* Merge in user overrides from the NMConnection's IPv6 setting */
- nm_ip6_config_merge_setting(config, s_ip, route_table, route_metric);
+ //XXX
+ (void) s_ip;
+ //nm_ip6_config_merge_setting (config,
+ // s_ip,
+ // route_table,
+ // route_metric);
if (!never_default && !nm_setting_ip_config_get_never_default(s_ip)) {
const NMPlatformIP6Route r = {
@@ -1865,19 +1850,26 @@ next:
.mss = mss,
};
- nm_ip6_config_add_route(config, &r, NULL);
+ nm_l3_config_data_add_route_6(l3cd, &r);
}
- nm_ip6_config_add_dependent_routes(config, route_table, route_metric, _is_device_vrf(self));
+ //XXX nm_l3_config_data_add_dependent_routes(l3cd,
+ //XXX AF_INET6,
+ //XXX route_table,
+ //XXX route_metric,
+ //XXX _is_device_vrf(self));
- if (priv->ip6_config) {
- nm_ip6_config_replace(priv->ip6_config, config, NULL);
- g_object_unref(config);
- } else {
- priv->ip6_config = config;
- nm_dbus_object_export(NM_DBUS_OBJECT(config));
- g_object_notify((GObject *) self, NM_ACTIVE_CONNECTION_IP6_CONFIG);
- }
+ //XXX
+#if 0
+ if (priv->ip6_config) {
+ nm_ip6_config_replace (priv->ip6_config, config, NULL);
+ g_object_unref (config);
+ } else {
+ priv->ip6_config = config;
+ nm_dbus_object_export (NM_DBUS_OBJECT (config));
+ g_object_notify ((GObject *) self, NM_ACTIVE_CONNECTION_IP6_CONFIG);
+ }
+#endif
nm_vpn_connection_config_maybe_complete(self, TRUE);
}
@@ -2423,28 +2415,12 @@ nm_vpn_connection_get_banner(NMVpnConnection *self)
return NM_VPN_CONNECTION_GET_PRIVATE(self)->banner;
}
-NMProxyConfig *
-nm_vpn_connection_get_proxy_config(NMVpnConnection *self)
+const NML3ConfigData *
+nm_vpn_connection_get_l3cd(NMVpnConnection *self, int addr_family)
{
g_return_val_if_fail(NM_IS_VPN_CONNECTION(self), NULL);
- return NM_VPN_CONNECTION_GET_PRIVATE(self)->proxy_config;
-}
-
-NMIP4Config *
-nm_vpn_connection_get_ip4_config(NMVpnConnection *self)
-{
- g_return_val_if_fail(NM_IS_VPN_CONNECTION(self), NULL);
-
- return NM_VPN_CONNECTION_GET_PRIVATE(self)->ip4_config;
-}
-
-NMIP6Config *
-nm_vpn_connection_get_ip6_config(NMVpnConnection *self)
-{
- g_return_val_if_fail(NM_IS_VPN_CONNECTION(self), NULL);
-
- return NM_VPN_CONNECTION_GET_PRIVATE(self)->ip6_config;
+ return NM_VPN_CONNECTION_GET_PRIVATE(self)->l3cd_x[NM_IS_IPv4(addr_family)];
}
static int
@@ -2820,8 +2796,6 @@ dispose(GObject *object)
nm_clear_pointer(&priv->connect_hash, g_variant_unref);
- nm_clear_pointer(&priv->ip4_dev_route_blacklist, g_ptr_array_unref);
-
nm_clear_g_source(&priv->connect_timeout);
dispatcher_cleanup(self);
@@ -2830,9 +2804,6 @@ dispose(GObject *object)
nm_clear_g_cancellable(&priv->cancellable);
- g_clear_object(&priv->proxy_config);
- nm_dbus_object_clear_and_unexport(&priv->ip4_config);
- nm_dbus_object_clear_and_unexport(&priv->ip6_config);
g_clear_object(&priv->proxy);
g_clear_object(&priv->plugin_info);
@@ -2859,7 +2830,8 @@ finalize(GObject *object)
g_clear_object(&priv->netns);
}
-static gboolean
+//XXX
+_nm_unused static gboolean
ip_config_valid(VpnState state)
{
return (state == STATE_PRE_UP || state == STATE_ACTIVATED);
@@ -2879,14 +2851,14 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
g_value_set_string(value, priv->banner ?: "");
break;
case PROP_IP4_CONFIG:
- nm_dbus_utils_g_value_set_object_path(value,
- ip_config_valid(priv->vpn_state) ? priv->ip4_config
- : NULL);
+ //XXX nm_dbus_utils_g_value_set_object_path(value,
+ //XXX ip_config_valid(priv->vpn_state) ? priv->ip4_config
+ //XXX : NULL);
break;
case PROP_IP6_CONFIG:
- nm_dbus_utils_g_value_set_object_path(value,
- ip_config_valid(priv->vpn_state) ? priv->ip6_config
- : NULL);
+ //XXX nm_dbus_utils_g_value_set_object_path(value,
+ //XXX ip_config_valid(priv->vpn_state) ? priv->ip6_config
+ //XXX : NULL);
break;
case PROP_MASTER:
parent_dev = nm_active_connection_get_device(NM_ACTIVE_CONNECTION(object));
diff --git a/src/core/vpn/nm-vpn-connection.h b/src/core/vpn/nm-vpn-connection.h
index 0209ea3d60..940a20d7a3 100644
--- a/src/core/vpn/nm-vpn-connection.h
+++ b/src/core/vpn/nm-vpn-connection.h
@@ -54,10 +54,8 @@ void nm_vpn_connection_disconnect(NMVpnConnection * self,
NMActiveConnectionStateReason reason,
gboolean quitting);
-NMProxyConfig *nm_vpn_connection_get_proxy_config(NMVpnConnection *self);
+const NML3ConfigData *nm_vpn_connection_get_l3cd(NMVpnConnection *self, int addr_family);
-NMIP4Config * nm_vpn_connection_get_ip4_config(NMVpnConnection *self);
-NMIP6Config * nm_vpn_connection_get_ip6_config(NMVpnConnection *self);
const char * nm_vpn_connection_get_ip_iface(NMVpnConnection *self, gboolean fallback_device);
int nm_vpn_connection_get_ip_ifindex(NMVpnConnection *self, gboolean fallback_device);
guint32 nm_vpn_connection_get_ip4_internal_gateway(NMVpnConnection *self);
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c
index 4ea545a434..867ef7b501 100644
--- a/src/libnm-platform/nm-linux-platform.c
+++ b/src/libnm-platform/nm-linux-platform.c
@@ -3530,7 +3530,6 @@ rta_multipath_done:;
obj = nmp_object_new(is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
- obj->ip_route.is_external = TRUE;
obj->ip_route.type_coerced = nm_platform_route_type_coerce(rtm->rtm_type);
obj->ip_route.table_coerced = nm_platform_route_table_coerce(
tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : (guint32) rtm->rtm_table);
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 5d4ec037ec..ee8748c631 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -4520,12 +4520,6 @@ nm_platform_ip_route_sync(NMPlatform *self,
conf_o = routes->pdata[i];
- if (NMP_OBJECT_CAST_IP_ROUTE(conf_o)->is_external) {
- /* This route is added externally. We don't have our own agenda to
- * add it, so skip. */
- continue;
- }
-
/* User space cannot add IPv6 routes with metric 0. However, kernel can, and we might track such
* routes in @route as they are present external. As we already skipped external routes above,
* we don't expect a user's choice to add such a route (it won't work anyway). */
@@ -4721,24 +4715,6 @@ sync_route_add:
}
if (routes_prune) {
- if (routes) {
- for (i = 0; i < routes->len; i++) {
- conf_o = routes->pdata[i];
-
- if (NMP_OBJECT_CAST_IP_ROUTE(conf_o)->is_external) {
- /* this is only to catch the case where an external route is
- * both in @routes and @routes_prune list. In that case,
- * @routes should win and we should not remove the address. */
- if (!routes_idx) {
- routes_idx = g_hash_table_new((GHashFunc) nmp_object_id_hash,
- (GEqualFunc) nmp_object_id_equal);
- }
- g_hash_table_add(routes_idx, (gpointer) conf_o);
- continue;
- }
- }
- }
-
for (i = 0; i < routes_prune->len; i++) {
const NMPObject *prune_o;
@@ -6273,7 +6249,6 @@ nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf
"%s" /* flags */
"%s" /* label */
" src %s"
- "%s" /* external */
"%s" /* a_acd_not_ready */
"%s" /* a_assume_config_once */
"",
@@ -6293,7 +6268,6 @@ nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf
_to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)),
str_label,
nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)),
- address->external ? " ext" : "",
address->a_acd_not_ready ? " ip4acd-not-ready" : "",
address->a_assume_config_once ? " assume-config-once" : "");
g_free(str_peer);
@@ -6415,7 +6389,6 @@ nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf
buf,
len,
"%s/%d lft %s pref %s%s%s%s%s src %s"
- "%s" /* external */
"%s" /* a_assume_config_once */
"",
s_address,
@@ -6427,7 +6400,6 @@ nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf
str_dev,
_to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)),
nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)),
- address->external ? " external" : "",
address->a_assume_config_once ? " assume-config-once" : "");
g_free(str_peer);
return buf;
@@ -6519,7 +6491,6 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
"%s" /* initcwnd */
"%s" /* initrwnd */
"%s" /* mtu */
- "%s" /* is_external */
"%s" /* r_assume_config_once */
"",
nm_net_aux_rtnl_rtntype_n2a_maybe_buf(nm_platform_route_type_uncoerce(route->type_coerced),
@@ -6577,7 +6548,6 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
route->lock_mtu ? "lock " : "",
route->mtu)
: "",
- route->is_external ? " is-external" : "",
route->r_assume_config_once ? " assume-config-once" : "");
return buf;
}
@@ -6648,7 +6618,6 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
"%s" /* initrwnd */
"%s" /* mtu */
"%s" /* pref */
- "%s" /* is_external */
"%s" /* r_assume_config_once */
"",
nm_net_aux_rtnl_rtntype_n2a_maybe_buf(nm_platform_route_type_uncoerce(route->type_coerced),
@@ -6710,7 +6679,6 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
" pref %s",
nm_icmpv6_router_pref_to_string(route->rt_pref, str_pref2, sizeof(str_pref2)))
: "",
- route->is_external ? " is-external" : "",
route->r_assume_config_once ? " assume-config-once" : "");
return buf;
@@ -7845,7 +7813,6 @@ nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState
obj->address,
obj->peer_address,
NM_HASH_COMBINE_BOOLS(guint8,
- obj->external,
obj->use_ip4_broadcast_address,
obj->a_acd_not_ready,
obj->a_assume_config_once));
@@ -7869,7 +7836,6 @@ nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a, const NMPlatformIP4Ad
NM_CMP_FIELD(a, b, preferred);
NM_CMP_FIELD(a, b, n_ifa_flags);
NM_CMP_FIELD_STR(a, b, label);
- NM_CMP_FIELD_UNSAFE(a, b, external);
NM_CMP_FIELD_UNSAFE(a, b, a_acd_not_ready);
NM_CMP_FIELD_UNSAFE(a, b, a_assume_config_once);
return 0;
@@ -7888,7 +7854,7 @@ nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState
obj->plen,
obj->address,
obj->peer_address,
- NM_HASH_COMBINE_BOOLS(guint8, obj->external, obj->a_assume_config_once));
+ NM_HASH_COMBINE_BOOLS(guint8, obj->a_assume_config_once));
}
int
@@ -7908,7 +7874,6 @@ nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a, const NMPlatformIP6Ad
NM_CMP_FIELD(a, b, lifetime);
NM_CMP_FIELD(a, b, preferred);
NM_CMP_FIELD(a, b, n_ifa_flags);
- NM_CMP_FIELD_UNSAFE(a, b, external);
NM_CMP_FIELD_UNSAFE(a, b, a_assume_config_once);
return 0;
}
@@ -8018,7 +7983,6 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj,
obj->lock_initcwnd,
obj->lock_initrwnd,
obj->lock_mtu,
- obj->is_external,
obj->r_assume_config_once));
break;
}
@@ -8110,7 +8074,6 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a,
NM_CMP_FIELD(a, b, initrwnd);
NM_CMP_FIELD(a, b, mtu);
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL) {
- NM_CMP_FIELD_UNSAFE(a, b, is_external);
NM_CMP_FIELD_UNSAFE(a, b, r_assume_config_once);
}
break;
@@ -8205,7 +8168,6 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj,
obj->lock_initcwnd,
obj->lock_initrwnd,
obj->lock_mtu,
- obj->is_external,
obj->r_assume_config_once),
obj->window,
obj->cwnd,
@@ -8290,7 +8252,6 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a,
else
NM_CMP_FIELD(a, b, rt_pref);
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL) {
- NM_CMP_FIELD_UNSAFE(a, b, is_external);
NM_CMP_FIELD_UNSAFE(a, b, r_assume_config_once);
}
break;
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index 116efbeec5..a3534f3e81 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -318,10 +318,6 @@ typedef enum {
* IFA_FLAGS attribute. */ \
guint32 n_ifa_flags; \
\
- /* FIXME(l3cfg): the external marker won't be necessary anymore, because we only
- * merge addresses we care about, and ignore (don't remove) external addresses. */ \
- bool external : 1; \
- \
bool use_ip4_broadcast_address : 1; \
\
/* Whether the address is should be configured once during assume. This is a meta flag
@@ -471,14 +467,6 @@ typedef union {
* the "table_coerced" field is ignored (unlike for the metric). */ \
bool table_any : 1; \
\
- /* This route is tracked as external route, that is not a route that NetworkManager
- * actively wants to add, but a route that was added externally. In some cases, such
- * a route should be ignored.
- *
- * Note that unlike most other fields here, this flag only exists inside NetworkManager
- * and is not reflected on netlink. */ \
- bool is_external : 1; \
- \
/* Whether the route is should be configured once during assume. This is a meta flag
* that is not honored by NMPlatform (netlink code). Instead, it can be used by the upper
* layers which use NMPlatformIPRoute to track routes that should be configured. */ \
diff --git a/src/libnm-systemd-core/meson.build b/src/libnm-systemd-core/meson.build
index 7ecf31640a..66e7cc82c4 100644
--- a/src/libnm-systemd-core/meson.build
+++ b/src/libnm-systemd-core/meson.build
@@ -18,8 +18,6 @@ libnm_systemd_core = static_library(
'src/libsystemd-network/sd-dhcp-lease.c',
'src/libsystemd-network/sd-dhcp6-client.c',
'src/libsystemd-network/sd-dhcp6-lease.c',
- 'src/libsystemd-network/sd-ipv4acd.c',
- 'src/libsystemd-network/sd-ipv4ll.c',
'src/libsystemd-network/sd-lldp.c',
'src/libsystemd/sd-event/event-util.c',
'src/libsystemd/sd-event/sd-event.c',
diff --git a/src/libnm-systemd-core/nm-sd.h b/src/libnm-systemd-core/nm-sd.h
index f346197440..c52f7cfe77 100644
--- a/src/libnm-systemd-core/nm-sd.h
+++ b/src/libnm-systemd-core/nm-sd.h
@@ -9,7 +9,6 @@
#include "src/systemd/sd-dhcp-client.h"
#include "src/systemd/sd-dhcp6-client.h"
#include "src/systemd/sd-lldp.h"
-#include "src/systemd/sd-ipv4ll.h"
/*****************************************************************************/
diff --git a/tools/run-nm-test.sh b/tools/run-nm-test.sh
index 81b94ec648..355a436600 100755
--- a/tools/run-nm-test.sh
+++ b/tools/run-nm-test.sh
@@ -362,7 +362,6 @@ if [ $HAS_ERRORS -eq 0 ]; then
# valgrind doesn't support setns syscall and spams the logfile.
# hack around it...
case "$TEST_NAME" in
- 'test-acd' | \
'test-address-linux' | \
'test-cleanup-linux' | \
'test-config' | \