summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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' | \