mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-20 09:20:04 +01:00
core: rework IP configuration in NetworkManager using layer 3 configuration
Completely rework IP configuration in the daemon. Use NML3Cfg as layer 3 manager for the IP configuration of an interface. Use NML3ConfigData as pieces of configuration that the various components collect and configure. NMDevice is managing most of the IP configuration at a higher level, that is, it starts DHCP and other IP methods. Rework the state handling there. This is a huge rework of how NetworkManager daemon handles IP configuration. Some fallout is to be expected. It appears the patch deletes many lines of code. That is not accurate, because you also have to count the files `src/core/nm-l3*`, which were unused previously. Co-authored-by: Beniamino Galvani <bgalvani@redhat.com>
This commit is contained in:
parent
403acb1f80
commit
58287cbcc0
135 changed files with 12299 additions and 23336 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -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
|
||||
|
|
@ -249,7 +248,6 @@ test-*.trs
|
|||
/src/core/dhcp/tests/test-dhcp-options
|
||||
/src/core/dhcp/tests/test-dhcp-utils
|
||||
/src/core/dnsmasq/tests/test-dnsmasq-utils
|
||||
/src/core/nm-iface-helper
|
||||
/src/core/ndisc/tests/test-ndisc-fake
|
||||
/src/core/ndisc/tests/test-ndisc-linux
|
||||
/src/core/platform/tests/monitor
|
||||
|
|
@ -406,10 +404,12 @@ 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
|
||||
/src/core/initrd/tests/test-ibft-reader
|
||||
/src/core/nm-iface-helper
|
||||
/src/devices/bluetooth/tests/nm-bt-test
|
||||
/src/devices/tests/test-acd
|
||||
/src/devices/tests/test-arping
|
||||
|
|
|
|||
75
Makefile.am
75
Makefile.am
|
|
@ -2074,9 +2074,6 @@ src_core_ldflags = $(CODE_COVERAGE_LDFLAGS)
|
|||
sbin_PROGRAMS += \
|
||||
src/core/NetworkManager
|
||||
|
||||
libexec_PROGRAMS += \
|
||||
src/core/nm-iface-helper
|
||||
|
||||
noinst_LTLIBRARIES += \
|
||||
src/core/libNetworkManagerBase.la \
|
||||
src/core/libNetworkManager.la \
|
||||
|
|
@ -2323,8 +2320,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-rx.c \
|
||||
src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h \
|
||||
src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c \
|
||||
|
|
@ -2342,8 +2337,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-rx.h \
|
||||
src/libnm-systemd-core/src/systemd/sd-lldp.h \
|
||||
src/libnm-systemd-core/src/systemd/sd-ndisc.h \
|
||||
|
|
@ -2394,10 +2387,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 \
|
||||
|
|
@ -2436,8 +2425,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 \
|
||||
|
|
@ -2513,6 +2500,8 @@ src_core_libNetworkManager_la_SOURCES = \
|
|||
src/core/dnsmasq/nm-dnsmasq-utils.c \
|
||||
src/core/dnsmasq/nm-dnsmasq-utils.h \
|
||||
\
|
||||
src/core/ppp/nm-ppp-mgr.c \
|
||||
src/core/ppp/nm-ppp-mgr.h \
|
||||
src/core/ppp/nm-ppp-manager-call.c \
|
||||
src/core/ppp/nm-ppp-manager-call.h \
|
||||
src/core/ppp/nm-ppp-manager.h \
|
||||
|
|
@ -2586,8 +2575,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 \
|
||||
|
|
@ -2721,44 +2708,6 @@ $(src_core_NetworkManager_OBJECTS): $(src_libnm_core_public_mkenums_h)
|
|||
|
||||
###############################################################################
|
||||
|
||||
src_core_nm_iface_helper_CPPFLAGS = $(src_core_cppflags)
|
||||
|
||||
src_core_nm_iface_helper_SOURCES = \
|
||||
src/core/nm-iface-helper.c
|
||||
|
||||
src_core_nm_iface_helper_LDADD = \
|
||||
src/core/libNetworkManagerBase.la \
|
||||
src/libnm-core-aux-extern/libnm-core-aux-extern.la \
|
||||
src/libnm-core-impl/libnm-core-impl.la \
|
||||
$(libnm_crypto_lib) \
|
||||
src/libnm-core-aux-intern/libnm-core-aux-intern.la \
|
||||
src/libnm-platform/libnm-platform.la \
|
||||
src/libnm-base/libnm-base.la \
|
||||
src/libnm-log-core/libnm-log-core.la \
|
||||
src/libnm-udev-aux/libnm-udev-aux.la \
|
||||
src/libnm-glib-aux/libnm-glib-aux.la \
|
||||
src/libnm-std-aux/libnm-std-aux.la \
|
||||
src/libnm-systemd-core/libnm-systemd-core.la \
|
||||
src/libnm-systemd-shared/libnm-systemd-shared.la \
|
||||
src/n-acd/libn-acd.la \
|
||||
src/n-dhcp4/libn-dhcp4.la \
|
||||
src/c-rbtree/libc-rbtree.la \
|
||||
src/c-siphash/libc-siphash.la \
|
||||
$(SYSTEMD_JOURNAL_LIBS) \
|
||||
$(GLIB_LIBS) \
|
||||
$(LIBUDEV_LIBS) \
|
||||
$(LIBNDP_LIBS) \
|
||||
$(DL_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
src_core_nm_iface_helper_LDFLAGS = \
|
||||
-Wl,--version-script="$(srcdir)/linker-script-binary.ver" \
|
||||
$(SANITIZER_EXEC_LDFLAGS)
|
||||
|
||||
$(src_core_nm_iface_helper_OBJECTS): $(src_libnm_core_public_mkenums_h)
|
||||
|
||||
###############################################################################
|
||||
|
||||
noinst_LTLIBRARIES += src/nm-initrd-generator/libnmi-core.la
|
||||
|
||||
src_nm_initrd_generator_libnmi_core_la_CPPFLAGS = \
|
||||
|
|
@ -4275,20 +4224,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
|
||||
|
|
@ -4391,22 +4334,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)
|
||||
|
|
@ -4434,8 +4367,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)
|
||||
|
|
|
|||
|
|
@ -1000,7 +1000,6 @@ fi
|
|||
%ghost %attr(755, root, root) %{_sbindir}/ifdown
|
||||
%{_libexecdir}/nm-dhcp-helper
|
||||
%{_libexecdir}/nm-dispatcher
|
||||
%{_libexecdir}/nm-iface-helper
|
||||
%{_libexecdir}/nm-initrd-generator
|
||||
%{_libexecdir}/nm-daemon-helper
|
||||
%{_libexecdir}/nm-sudo
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ src/core/dns/nm-dns-manager.c
|
|||
src/core/main-utils.c
|
||||
src/core/main.c
|
||||
src/core/nm-config.c
|
||||
src/core/nm-iface-helper.c
|
||||
src/core/nm-manager.c
|
||||
src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
|
||||
src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
|
||||
|
|
|
|||
|
|
@ -227,6 +227,21 @@ out:
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
nm_utils_ppp_ip_methods_enabled(NMConnection *connection,
|
||||
gboolean * out_ip4_enabled,
|
||||
gboolean * out_ip6_enabled)
|
||||
{
|
||||
NM_SET_OUT(out_ip4_enabled,
|
||||
nm_streq0(nm_utils_get_ip_config_method(connection, AF_INET),
|
||||
NM_SETTING_IP4_CONFIG_METHOD_AUTO));
|
||||
NM_SET_OUT(out_ip6_enabled,
|
||||
nm_streq0(nm_utils_get_ip_config_method(connection, AF_INET6),
|
||||
NM_SETTING_IP6_CONFIG_METHOD_AUTO));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
_nm_utils_complete_generic_with_params(NMPlatform * platform,
|
||||
NMConnection * connection,
|
||||
|
|
@ -1298,7 +1313,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 +1325,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 +1353,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,29 +1418,10 @@ 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)
|
||||
{
|
||||
|
|
@ -1425,8 +1429,8 @@ nm_utils_ip_addresses_to_dbus(int addr_family,
|
|||
GVariantBuilder builder_data;
|
||||
GVariantBuilder builder_legacy;
|
||||
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
gs_free const NMPObject **addresses = NULL;
|
||||
guint naddr;
|
||||
NMDedupMultiIter iter;
|
||||
const NMPObject *obj;
|
||||
guint i;
|
||||
|
||||
nm_assert_addr_family(addr_family);
|
||||
|
|
@ -1443,19 +1447,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 +1523,8 @@ nm_utils_ip_addresses_to_dbus(int addr_family,
|
|||
: &in6addr_any));
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
@ -1654,6 +1652,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ const char *nm_utils_get_ip_config_method(NMConnection *connection, int addr_fam
|
|||
|
||||
const char *nm_utils_get_shared_wifi_permission(NMConnection *connection);
|
||||
|
||||
void nm_utils_ppp_ip_methods_enabled(NMConnection *connection,
|
||||
gboolean * out_ip4_enabled,
|
||||
gboolean * out_ip6_enabled);
|
||||
|
||||
void _nm_utils_complete_generic_with_params(NMPlatform * platform,
|
||||
NMConnection * connection,
|
||||
const char * ctype,
|
||||
|
|
@ -195,12 +199,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 +274,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);
|
||||
|
||||
|
|
|
|||
368
src/core/README.l3cfg.md
Normal file
368
src/core/README.l3cfg.md
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
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"
|
||||
|
||||
TODO
|
||||
----
|
||||
|
||||
- Before considering an IP method completely activated, check that all addresses
|
||||
we want to configure are no longer tentative.
|
||||
For example, when activating a `connection.type=pppoe`, we might get an IPv6 address
|
||||
from the pppd daemon. We set that via
|
||||
`nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, ip_data->l3cd)`
|
||||
Note that this currently already is sufficient to make the IP method (as far as PPP
|
||||
is concerned), to be "ready".
|
||||
We should however wait for IPv6 DAD to complete. See how that is already done
|
||||
for ipmanual (`_dev_ipmanual_check_ready()`).
|
||||
|
||||
- NMDevicePPP fails to re-activate a profile that is currently active. This is not
|
||||
new on "next" branch, but also happened before. Have a pppoe profile active,
|
||||
and issue `nmcli connection up $PROFILE` again. This, as expected, brings down
|
||||
the device but fails to re-activate it. It's not trivial to fix (I think), because
|
||||
of the ip-ifindex madness. Check the logs. Test with contrib/scripts/test-ppp.sh
|
||||
script. Possibly affects other types.
|
||||
|
||||
- NMDevice's ip4_config_pre_commit() had only one effect, to call nm_modem_ip4_pre_commit()
|
||||
which set IFF_NOARP. That is currently dropped. Find a different way to achieve that.
|
||||
Theoretically, we still could do that from NML3Cfg's post-commit notification. But
|
||||
this really should be handled by NML3Cfg. That means, to disable IFF_NOARP needs somehow
|
||||
configured by NMDeviceModem -- possibly by setting a flag in NML3ConfigData that indicates
|
||||
to do this. Or maybe NML3Cfg should detect automatically when to set IFF_NOARP.
|
||||
|
||||
- `ipvx.method=auto` usually means autoconf6/DHCPv4, but it doesn't have to. For example
|
||||
with PPP/VPN it might mean that the IP configuration is provided by pppd/VPN or with
|
||||
Wi-Fi-P2P it might mean that the controller of a peer runs a DHCP server (shared).
|
||||
Now the parents implementation activate_stage3_ip_config() can no longer be overwritten
|
||||
by subclasses, and they always perform their steps. For subclasses to modify what a
|
||||
method means there is klass->get_ip_method_auto(self(). NMDeviceModem does not yet
|
||||
implement that, which is most certainly lacking. We need to test at least NMDeviceModem
|
||||
whether IP methods work correctly in this regard. Possibly other subclasses are affected
|
||||
too (NMDeviceBluetooth?).
|
||||
59
src/core/README.next.ip-config.md
Normal file
59
src/core/README.next.ip-config.md
Normal file
|
|
@ -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.
|
||||
|
|
@ -15,13 +15,12 @@
|
|||
#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-mgr.h"
|
||||
|
||||
#define _NMLOG_DEVICE_TYPE NMDeviceAdsl
|
||||
#include "devices/nm-device-logging.h"
|
||||
|
|
@ -34,14 +33,13 @@ typedef struct {
|
|||
guint carrier_poll_id;
|
||||
int atm_index;
|
||||
|
||||
/* PPP */
|
||||
NMPPPManager *ppp_manager;
|
||||
NMPppMgr *ppp_mgr;
|
||||
|
||||
/* RFC 2684 bridging (PPPoE over ATM) */
|
||||
int brfd;
|
||||
int nas_ifindex;
|
||||
char *nas_ifname;
|
||||
guint nas_update_id;
|
||||
char * nas_ifname;
|
||||
GSource *nas_update_source;
|
||||
guint nas_update_count;
|
||||
} NMDeviceAdslPrivate;
|
||||
|
||||
|
|
@ -271,7 +269,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 +282,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) {
|
||||
if (priv->nas_update_count <= 10) {
|
||||
|
||||
if (priv->nas_ifindex <= 0 && priv->nas_update_count <= 10) {
|
||||
/* Keep waiting for it to appear */
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
priv->nas_update_id = 0;
|
||||
|
||||
nm_clear_g_source_inst(&priv->nas_update_source);
|
||||
|
||||
if (priv->nas_ifindex <= 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 +319,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) {
|
||||
|
|
@ -359,35 +359,118 @@ 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_source = nm_g_timeout_add_source(100, nas_update_timeout_cb, self);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_ppp_mgr_cleanup(NMDeviceAdsl *self)
|
||||
{
|
||||
NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
|
||||
|
||||
nm_clear_pointer(&priv->ppp_mgr, nm_ppp_mgr_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
_ppp_mgr_stage3_maybe_ready(NMDeviceAdsl *self)
|
||||
{
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
|
||||
int IS_IPv4;
|
||||
|
||||
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
|
||||
const NMPppMgrIPData *ip_data;
|
||||
|
||||
ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_mgr, addr_family);
|
||||
if (ip_data->ip_received)
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, ip_data->l3cd);
|
||||
}
|
||||
|
||||
if (nm_ppp_mgr_get_state(priv->ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG)
|
||||
nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_READY, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data)
|
||||
{
|
||||
NMDeviceAdsl *self = NM_DEVICE_ADSL(user_data);
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMDeviceState device_state;
|
||||
|
||||
if (callback_data->callback_type != NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED)
|
||||
return;
|
||||
|
||||
device_state = nm_device_get_state(device);
|
||||
|
||||
if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) {
|
||||
if (device_state <= NM_DEVICE_STATE_ACTIVATED)
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, callback_data->data.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device_state < NM_DEVICE_STATE_IP_CONFIG) {
|
||||
if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) {
|
||||
gs_free char *old_name = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
if (!nm_device_take_over_link(device, callback_data->data.ifindex, &old_name, &error)) {
|
||||
_LOGW(LOGD_DEVICE | LOGD_PPP,
|
||||
"could not take control of link %d: %s",
|
||||
callback_data->data.ifindex,
|
||||
error->message);
|
||||
_ppp_mgr_cleanup(self);
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (old_name)
|
||||
nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_ADSL);
|
||||
|
||||
nm_device_activate_schedule_stage2_device_config(device, FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_ppp_mgr_stage3_maybe_ready(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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);
|
||||
|
||||
if (!priv->ppp_mgr) {
|
||||
gs_free_error GError *error = NULL;
|
||||
NMSettingAdsl * s_adsl;
|
||||
const char * protocol;
|
||||
NMActRequest * req;
|
||||
const char * ppp_iface;
|
||||
|
||||
req = nm_device_get_act_request(device);
|
||||
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
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)) {
|
||||
} 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_id == 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;
|
||||
|
|
@ -395,137 +478,67 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE(user_data);
|
||||
|
||||
switch (status) {
|
||||
case NM_PPP_STATUS_DISCONNECT:
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
|
||||
break;
|
||||
case NM_PPP_STATUS_DEAD:
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE(user_data);
|
||||
|
||||
if (!nm_device_set_ip_ifindex(device, ifindex)) {
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE(user_data);
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip4_config_start(NMDevice * device,
|
||||
NMIP4Config ** out_config,
|
||||
NMDeviceStateReason *out_failure_reason)
|
||||
{
|
||||
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);
|
||||
|
||||
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
|
||||
|
||||
g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
} else
|
||||
nm_assert(nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM));
|
||||
|
||||
/* PPPoE uses the NAS interface, not the ATM interface */
|
||||
if (nm_streq0(nm_setting_adsl_get_protocol(s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
|
||||
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");
|
||||
}
|
||||
|
||||
priv->ppp_manager = nm_ppp_manager_create(ppp_iface, &err);
|
||||
|
||||
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->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);
|
||||
|
||||
g_clear_object(&priv->ppp_manager);
|
||||
|
||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED);
|
||||
priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig){
|
||||
.netns = nm_device_get_netns(device),
|
||||
.parent_iface = ppp_iface,
|
||||
.callback = _ppp_mgr_callback,
|
||||
.user_data = self,
|
||||
.act_req = req,
|
||||
.ppp_username = nm_setting_adsl_get_username(s_adsl),
|
||||
.timeout_secs = 30,
|
||||
.baud_override = 0,
|
||||
}),
|
||||
&error);
|
||||
if (!priv->ppp_mgr) {
|
||||
_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_IP4_CONFIG,
|
||||
G_CALLBACK(ppp_ip4_config),
|
||||
self);
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
if (nm_ppp_mgr_get_state(priv->ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX)
|
||||
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);
|
||||
NMDeviceAdsl * self = NM_DEVICE_ADSL(device);
|
||||
NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
|
||||
NMPppMgrState ppp_state;
|
||||
|
||||
return NM_DEVICE_CLASS(nm_device_adsl_parent_class)
|
||||
->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
|
||||
if (!priv->ppp_mgr) {
|
||||
nm_assert_not_reached();
|
||||
return;
|
||||
}
|
||||
|
||||
ppp_state = nm_ppp_mgr_get_state(priv->ppp_mgr);
|
||||
|
||||
nm_assert(NM_IN_SET(ppp_state, NM_PPP_MGR_STATE_HAVE_IFINDEX, NM_PPP_MGR_STATE_HAVE_IP_CONFIG));
|
||||
|
||||
if (ppp_state < NM_PPP_MGR_STATE_HAVE_IP_CONFIG) {
|
||||
nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
_ppp_mgr_stage3_maybe_ready(self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -533,23 +546,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_mgr_cleanup(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,
|
||||
|
|
@ -700,7 +705,7 @@ nm_device_adsl_class_init(NMDeviceAdslClass *klass)
|
|||
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->act_stage3_ip_config = act_stage3_ip_config;
|
||||
device_class->deactivate = deactivate;
|
||||
|
||||
obj_properties[PROP_ATM_INDEX] =
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -425,43 +424,9 @@ static void
|
|||
ppp_failed(NMModem *modem, guint i_reason, gpointer user_data)
|
||||
{
|
||||
NMDevice * device = NM_DEVICE(user_data);
|
||||
NMDeviceBt * self = NM_DEVICE_BT(user_data);
|
||||
NMDeviceStateReason reason = i_reason;
|
||||
|
||||
switch (nm_device_get_state(device)) {
|
||||
case NM_DEVICE_STATE_PREPARE:
|
||||
case NM_DEVICE_STATE_CONFIG:
|
||||
case NM_DEVICE_STATE_NEED_AUTH:
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason);
|
||||
break;
|
||||
case NM_DEVICE_STATE_IP_CONFIG:
|
||||
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);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -547,22 +512,35 @@ 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_auto,
|
||||
const NMUtilsIPv6IfaceId *iid,
|
||||
int failure_reason_i,
|
||||
GError * error,
|
||||
gpointer user_data)
|
||||
{
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
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);
|
||||
g_return_if_fail(nm_device_devip_get_state(device, addr_family) == 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);
|
||||
_LOGW(LOGD_MB | LOGD_IP4, "retrieving IP configuration failed: %s", error->message);
|
||||
nm_device_devip_set_failed(device, addr_family, failure_reason_i);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config));
|
||||
if (do_auto) {
|
||||
if (IS_IPv4)
|
||||
nm_device_ip_method_dhcp4_start(device);
|
||||
else
|
||||
nm_device_ip_method_autoconf6_start(device);
|
||||
}
|
||||
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -687,7 +665,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);
|
||||
|
|
@ -992,35 +970,22 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
NMDeviceBt * self = NM_DEVICE_BT(device);
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self);
|
||||
|
||||
if (priv->connect_bt_type == NM_BT_CAPABILITY_DUN)
|
||||
nm_modem_act_stage2_config(priv->modem);
|
||||
|
||||
if (priv->connect_bt_type != NM_BT_CAPABILITY_DUN)
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
|
||||
return nm_modem_act_stage2_config(priv->modem, device, out_failure_reason);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (priv->connect_bt_type != NM_BT_CAPABILITY_DUN)
|
||||
goto out_chain_up;
|
||||
return;
|
||||
|
||||
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);
|
||||
if (nm_modem_stage3_ip_config_start(priv->modem, addr_family, device))
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1344,7 +1309,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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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__ */
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -14,37 +14,35 @@
|
|||
#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 "libnm-platform/nm-platform-utils.h"
|
||||
#include "nm-dcb.h"
|
||||
#include "settings/nm-settings-connection.h"
|
||||
#include "nm-config.h"
|
||||
#include "nm-device-ethernet-utils.h"
|
||||
#include "settings/nm-settings.h"
|
||||
#include "nm-device-factory.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "libnm-glib-aux/nm-uuid.h"
|
||||
#include "libnm-platform/nm-platform-utils.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 "nm-device-factory.h"
|
||||
#include "nm-device-private.h"
|
||||
#include "nm-device-veth.h"
|
||||
#include "nm-manager.h"
|
||||
#include "ppp/nm-ppp-mgr.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_RECONNECT_DELAY_MSEC 7000
|
||||
#define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */
|
||||
|
||||
#define SUPPLICANT_LNK_TIMEOUT_SEC 15
|
||||
|
|
@ -91,14 +89,16 @@ typedef struct _NMDeviceEthernetPrivate {
|
|||
guint lnk_timeout_id;
|
||||
|
||||
bool is_associated : 1;
|
||||
bool ready : 1;
|
||||
} supplicant;
|
||||
|
||||
NMActRequestGetSecretsCallId *wired_secrets_id;
|
||||
|
||||
/* PPPoE */
|
||||
NMPPPManager *ppp_manager;
|
||||
gint32 last_pppoe_time;
|
||||
guint pppoe_wait_id;
|
||||
struct {
|
||||
NMPppMgr *ppp_mgr;
|
||||
GSource * wait_source;
|
||||
gint64 last_pppoe_time_msec;
|
||||
} ppp_data;
|
||||
|
||||
/* DCB */
|
||||
DcbWait dcb_wait;
|
||||
|
|
@ -113,6 +113,8 @@ typedef struct _NMDeviceEthernetPrivate {
|
|||
bool ethtool_prev_set : 1;
|
||||
bool ethtool_prev_autoneg : 1;
|
||||
|
||||
bool stage2_ready_dcb : 1;
|
||||
|
||||
} NMDeviceEthernetPrivate;
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceEthernet, PROP_SPEED, PROP_S390_SUBCHANNELS, );
|
||||
|
|
@ -428,6 +430,7 @@ supplicant_interface_release(NMDeviceEthernet *self)
|
|||
nm_clear_g_source(&priv->supplicant.con_timeout_id);
|
||||
nm_clear_g_signal_handler(priv->supplicant.iface, &priv->supplicant.iface_state_id);
|
||||
nm_clear_g_signal_handler(priv->supplicant.iface, &priv->supplicant.auth_state_id);
|
||||
priv->supplicant.ready = FALSE;
|
||||
|
||||
if (priv->supplicant.iface) {
|
||||
nm_supplicant_interface_disconnect(priv->supplicant.iface);
|
||||
|
|
@ -468,14 +471,17 @@ 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,
|
||||
if (!wired_auth_is_optional(self)) {
|
||||
supplicant_interface_release(self);
|
||||
nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
_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 (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 =
|
||||
|
|
@ -484,11 +490,6 @@ wired_auth_cond_fail(NMDeviceEthernet *self, NMDeviceStateReason reason)
|
|||
G_CALLBACK(supplicant_auth_state_changed),
|
||||
self);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
supplicant_interface_release(self);
|
||||
nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -644,14 +645,15 @@ supplicant_iface_state_is_completed(NMDeviceEthernet *self, NMSupplicantInterfac
|
|||
if (state == NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) {
|
||||
nm_clear_g_source(&priv->supplicant.lnk_timeout_id);
|
||||
nm_clear_g_source(&priv->supplicant.con_timeout_id);
|
||||
priv->supplicant.ready = TRUE;
|
||||
|
||||
/* 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 +971,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 +1016,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,105 +1110,79 @@ carrier_changed(NMSupplicantInterface *iface, GParamSpec *pspec, NMDeviceEtherne
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* PPPoE */
|
||||
|
||||
static void
|
||||
ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
|
||||
_ppp_mgr_cleanup(NMDeviceEthernet *self)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE(user_data);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
|
||||
|
||||
switch (status) {
|
||||
case NM_PPP_STATUS_DISCONNECT:
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
|
||||
break;
|
||||
case NM_PPP_STATUS_DEAD:
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nm_clear_pointer(&priv->ppp_data.ppp_mgr, nm_ppp_mgr_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE(user_data);
|
||||
|
||||
if (!nm_device_set_ip_ifindex(device, ifindex)) {
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE(user_data);
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
pppoe_stage3_ip4_config_start(NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason)
|
||||
_ppp_mgr_stage3_maybe_ready(NMDeviceEthernet *self)
|
||||
{
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
|
||||
NMSettingPppoe * s_pppoe;
|
||||
NMActRequest * req;
|
||||
GError * err = NULL;
|
||||
int IS_IPv4;
|
||||
|
||||
req = nm_device_get_act_request(device);
|
||||
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
|
||||
const NMPppMgrIPData *ip_data;
|
||||
|
||||
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_device_get_iface(device), &err);
|
||||
|
||||
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));
|
||||
ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_data.ppp_mgr, addr_family);
|
||||
if (ip_data->ip_received)
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, ip_data->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_ppp_mgr_get_state(priv->ppp_data.ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG)
|
||||
nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_READY, NULL);
|
||||
}
|
||||
|
||||
g_clear_object(&priv->ppp_manager);
|
||||
static void
|
||||
_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data)
|
||||
{
|
||||
NMDeviceEthernet *self = NM_DEVICE_ETHERNET(user_data);
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMDeviceState device_state;
|
||||
|
||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED);
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
if (callback_data->callback_type != NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED)
|
||||
return;
|
||||
|
||||
device_state = nm_device_get_state(device);
|
||||
|
||||
if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) {
|
||||
if (device_state <= NM_DEVICE_STATE_ACTIVATED)
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, callback_data->data.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
if (device_state < NM_DEVICE_STATE_IP_CONFIG) {
|
||||
if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) {
|
||||
gs_free char *old_name = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
if (!nm_device_take_over_link(device, callback_data->data.ifindex, &old_name, &error)) {
|
||||
_LOGW(LOGD_DEVICE | LOGD_PPP,
|
||||
"could not take control of link %d: %s",
|
||||
callback_data->data.ifindex,
|
||||
error->message);
|
||||
_ppp_mgr_cleanup(self);
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (old_name)
|
||||
nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP);
|
||||
|
||||
nm_device_activate_schedule_stage2_device_config(device, FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_ppp_mgr_stage3_maybe_ready(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1351,7 +1330,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,71 +1386,30 @@ 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;
|
||||
|
||||
/* 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 */
|
||||
if (!nm_device_has_carrier(NM_DEVICE(self))) {
|
||||
_LOGD(LOGD_DEVICE | LOGD_ETHER,
|
||||
"delay supplicant initialization until carrier goes up");
|
||||
priv->carrier_id = g_signal_connect(self,
|
||||
"notify::" NM_DEVICE_CARRIER,
|
||||
G_CALLBACK(carrier_changed),
|
||||
self);
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
return supplicant_check_secrets_needed(self, out_failure_reason);
|
||||
}
|
||||
}
|
||||
|
||||
wake_on_lan_enable(device);
|
||||
|
||||
/* DCB and FCoE setup */
|
||||
s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_DCB);
|
||||
if (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))) {
|
||||
if (!dcb_enable(device)) {
|
||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED);
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
} else {
|
||||
_LOGD(LOGD_DCB, "waiting for carrier (preenable up)");
|
||||
priv->dcb_wait = DCB_WAIT_CARRIER_PREENABLE_UP;
|
||||
priv->dcb_timeout_id = g_timeout_add_seconds(4, dcb_carrier_timeout, device);
|
||||
}
|
||||
|
||||
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;
|
||||
if (nm_streq(connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
|
||||
if (!priv->ppp_data.ppp_mgr) {
|
||||
gs_free_error GError *error = NULL;
|
||||
NMSettingPppoe * s_pppoe;
|
||||
NMSettingPpp * s_ppp;
|
||||
|
||||
s_ppp = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPP);
|
||||
if (s_ppp) {
|
||||
|
|
@ -1493,50 +1431,126 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
mxu + PPPOE_ENCAP_OVERHEAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return do_postpone ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
}
|
||||
req = nm_device_get_act_request(device);
|
||||
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip_config_start(NMDevice * device,
|
||||
int addr_family,
|
||||
gpointer * out_config,
|
||||
NMDeviceStateReason *out_failure_reason)
|
||||
{
|
||||
NMSettingConnection *s_con;
|
||||
const char * connection_type;
|
||||
int ifindex;
|
||||
s_pppoe = _nm_connection_get_setting(connection, NM_TYPE_SETTING_PPPOE);
|
||||
g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
ifindex = nm_device_get_ifindex(device);
|
||||
|
||||
if (ifindex <= 0)
|
||||
priv->ppp_data.ppp_mgr =
|
||||
nm_ppp_mgr_start(&((const NMPppMgrConfig){
|
||||
.netns = nm_device_get_netns(device),
|
||||
.parent_iface = nm_device_get_iface(device),
|
||||
.callback = _ppp_mgr_callback,
|
||||
.user_data = self,
|
||||
.act_req = req,
|
||||
.ppp_username = nm_setting_pppoe_get_username(s_pppoe),
|
||||
.timeout_secs = 30,
|
||||
.baud_override = 0,
|
||||
}),
|
||||
&error);
|
||||
if (!priv->ppp_data.ppp_mgr) {
|
||||
_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;
|
||||
|
||||
if (addr_family == AF_INET) {
|
||||
s_con = nm_device_get_applied_setting(device, NM_TYPE_SETTING_CONNECTION);
|
||||
|
||||
g_return_val_if_fail(s_con, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return NM_DEVICE_CLASS(nm_device_ethernet_parent_class)
|
||||
->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
if (nm_ppp_mgr_get_state(priv->ppp_data.ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX)
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
/* 802.1x has to run before any IP configuration since the 802.1x auth
|
||||
* process opens the port up for normal traffic.
|
||||
*/
|
||||
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: we always return from this. stage2 must be re-entrant, and
|
||||
* process all the necessary steps. Just returning for 8021x is wrong. */
|
||||
|
||||
if (priv->supplicant.ready)
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
|
||||
if (!nm_device_has_carrier(NM_DEVICE(self))) {
|
||||
_LOGD(LOGD_DEVICE | LOGD_ETHER,
|
||||
"delay supplicant initialization until carrier goes up");
|
||||
priv->carrier_id = g_signal_connect(self,
|
||||
"notify::" NM_DEVICE_CARRIER,
|
||||
G_CALLBACK(carrier_changed),
|
||||
self);
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
return supplicant_check_secrets_needed(self, out_failure_reason);
|
||||
}
|
||||
}
|
||||
|
||||
wake_on_lan_enable(device);
|
||||
|
||||
/* DCB and FCoE setup */
|
||||
s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_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))) {
|
||||
if (!dcb_enable(device)) {
|
||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED);
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
} else {
|
||||
_LOGD(LOGD_DCB, "waiting for carrier (preenable up)");
|
||||
priv->dcb_wait = DCB_WAIT_CARRIER_PREENABLE_UP;
|
||||
priv->dcb_timeout_id = g_timeout_add_seconds(4, dcb_carrier_timeout, device);
|
||||
}
|
||||
|
||||
priv->dcb_handle_carrier_changes = TRUE;
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force)
|
||||
{
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device);
|
||||
|
||||
/* MTU only set for plain ethernet */
|
||||
if (NM_DEVICE_ETHERNET_GET_PRIVATE(device)->ppp_manager)
|
||||
if (priv->ppp_data.ppp_mgr)
|
||||
return 0;
|
||||
|
||||
return nm_device_get_configured_mtu_for_wired(device, out_source, out_force);
|
||||
}
|
||||
|
||||
static void
|
||||
act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
{
|
||||
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
|
||||
NMPppMgrState ppp_state;
|
||||
|
||||
if (!priv->ppp_data.ppp_mgr)
|
||||
return;
|
||||
|
||||
ppp_state = nm_ppp_mgr_get_state(priv->ppp_data.ppp_mgr);
|
||||
|
||||
nm_assert(NM_IN_SET(ppp_state, NM_PPP_MGR_STATE_HAVE_IFINDEX, NM_PPP_MGR_STATE_HAVE_IP_CONFIG));
|
||||
|
||||
if (ppp_state < NM_PPP_MGR_STATE_HAVE_IP_CONFIG) {
|
||||
nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
_ppp_mgr_stage3_maybe_ready(self);
|
||||
}
|
||||
|
||||
static void
|
||||
deactivate(NMDevice *device)
|
||||
{
|
||||
|
|
@ -1546,19 +1560,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_mgr_cleanup(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 +1583,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 +1945,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 +2044,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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -7,16 +7,14 @@
|
|||
|
||||
#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"
|
||||
#include "nm-manager.h"
|
||||
#include "nm-setting-pppoe.h"
|
||||
#include "libnm-platform/nm-platform.h"
|
||||
#include "ppp/nm-ppp-manager.h"
|
||||
#include "ppp/nm-ppp-manager-call.h"
|
||||
#include "ppp/nm-ppp-status.h"
|
||||
#include "ppp/nm-ppp-mgr.h"
|
||||
|
||||
#define _NMLOG_DEVICE_TYPE NMDevicePpp
|
||||
#include "nm-device-logging.h"
|
||||
|
|
@ -24,8 +22,7 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMDevicePppPrivate {
|
||||
NMPPPManager *ppp_manager;
|
||||
NMIP4Config * ip4_config;
|
||||
NMPppMgr *ppp_mgr;
|
||||
} NMDevicePppPrivate;
|
||||
|
||||
struct _NMDevicePpp {
|
||||
|
|
@ -42,85 +39,91 @@ G_DEFINE_TYPE(NMDevicePpp, nm_device_ppp, NM_TYPE_DEVICE)
|
|||
#define NM_DEVICE_PPP_GET_PRIVATE(self) \
|
||||
_NM_GET_PRIVATE(self, NMDevicePpp, NM_IS_DEVICE_PPP, NMDevice)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NMDeviceCapabilities
|
||||
get_generic_capabilities(NMDevice *device)
|
||||
{
|
||||
return NM_DEVICE_CAP_IS_SOFTWARE;
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE(user_data);
|
||||
/*****************************************************************************/
|
||||
|
||||
switch (status) {
|
||||
case NM_PPP_STATUS_DISCONNECT:
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
|
||||
break;
|
||||
case NM_PPP_STATUS_DEAD:
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
static void
|
||||
_ppp_mgr_cleanup(NMDevicePpp *self)
|
||||
{
|
||||
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
|
||||
|
||||
nm_clear_pointer(&priv->ppp_mgr, nm_ppp_mgr_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data)
|
||||
_ppp_mgr_stage3_maybe_ready(NMDevicePpp *self)
|
||||
{
|
||||
NMDevice * device = NM_DEVICE(user_data);
|
||||
NMDevicePpp * self = NM_DEVICE_PPP(device);
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
|
||||
int IS_IPv4;
|
||||
|
||||
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
|
||||
const NMPppMgrIPData *ip_data;
|
||||
|
||||
ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_mgr, addr_family);
|
||||
if (ip_data->ip_received)
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, ip_data->l3cd);
|
||||
}
|
||||
|
||||
if (nm_ppp_mgr_get_state(priv->ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG)
|
||||
nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_READY, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data)
|
||||
{
|
||||
NMDevicePpp * self = NM_DEVICE_PPP(user_data);
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMDeviceState device_state;
|
||||
|
||||
if (callback_data->callback_type != NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED)
|
||||
return;
|
||||
|
||||
device_state = nm_device_get_state(device);
|
||||
|
||||
if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) {
|
||||
if (device_state <= NM_DEVICE_STATE_ACTIVATED)
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, callback_data->data.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device_state < NM_DEVICE_STATE_IP_CONFIG) {
|
||||
if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) {
|
||||
gs_free char *old_name = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
if (!nm_device_take_over_link(device, ifindex, &old_name, &error)) {
|
||||
if (!nm_device_take_over_link(device, callback_data->data.ifindex, &old_name, &error)) {
|
||||
_LOGW(LOGD_DEVICE | LOGD_PPP,
|
||||
"could not take control of link %d: %s",
|
||||
ifindex,
|
||||
callback_data->data.ifindex,
|
||||
error->message);
|
||||
_ppp_mgr_cleanup(self);
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
|
||||
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
_ppp_ip4_config_handle(NMDevicePpp *self)
|
||||
{
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
|
||||
|
||||
if (!priv->ip4_config)
|
||||
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)));
|
||||
nm_device_activate_schedule_stage2_device_config(device, FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_ppp_mgr_stage3_maybe_ready(self);
|
||||
}
|
||||
|
||||
static void
|
||||
ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
|
||||
{
|
||||
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);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error)
|
||||
|
|
@ -149,7 +152,9 @@ 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;
|
||||
|
||||
if (!priv->ppp_mgr) {
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
req = nm_device_get_act_request(device);
|
||||
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
|
@ -157,77 +162,70 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
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->ppp_manager
|
||||
|| !nm_ppp_manager_start(priv->ppp_manager,
|
||||
req,
|
||||
nm_setting_pppoe_get_username(s_pppoe),
|
||||
30,
|
||||
0,
|
||||
&error)) {
|
||||
priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig){
|
||||
.netns = nm_device_get_netns(device),
|
||||
.parent_iface = nm_setting_pppoe_get_parent(s_pppoe),
|
||||
.callback = _ppp_mgr_callback,
|
||||
.user_data = self,
|
||||
.act_req = req,
|
||||
.ppp_username = nm_setting_pppoe_get_username(s_pppoe),
|
||||
.timeout_secs = 30,
|
||||
.baud_override = 0,
|
||||
}),
|
||||
&error);
|
||||
if (!priv->ppp_mgr) {
|
||||
_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);
|
||||
*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_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;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip_config_start(NMDevice * device,
|
||||
int addr_family,
|
||||
gpointer * out_config,
|
||||
NMDeviceStateReason *out_failure_reason)
|
||||
{
|
||||
if (addr_family == AF_INET) {
|
||||
NMDevicePpp * self = NM_DEVICE_PPP(device);
|
||||
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return NM_DEVICE_CLASS(nm_device_ppp_parent_class)
|
||||
->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
|
||||
if (nm_ppp_mgr_get_state(priv->ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX)
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
{
|
||||
NMDevicePpp * self = NM_DEVICE_PPP(device);
|
||||
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
|
||||
NMPppMgrState ppp_state;
|
||||
|
||||
if (!priv->ppp_mgr) {
|
||||
nm_assert_not_reached();
|
||||
return;
|
||||
}
|
||||
|
||||
ppp_state = nm_ppp_mgr_get_state(priv->ppp_mgr);
|
||||
|
||||
nm_assert(NM_IN_SET(ppp_state, NM_PPP_MGR_STATE_HAVE_IFINDEX, NM_PPP_MGR_STATE_HAVE_IP_CONFIG));
|
||||
|
||||
if (ppp_state < NM_PPP_MGR_STATE_HAVE_IP_CONFIG) {
|
||||
nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
_ppp_mgr_stage3_maybe_ready(self);
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_ip_method_auto(NMDevice *device, int addr_family)
|
||||
{
|
||||
if (NM_IS_IPv4(addr_family)) {
|
||||
/* We cannot do DHCPv4 on a PPP link, instead we get "auto" IP addresses
|
||||
* by pppd. Return "manual" here, which has the suitable effect to a
|
||||
* (zero) manual addresses in addition. */
|
||||
return NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
|
||||
}
|
||||
|
||||
/* We can do autoconf6 on an PPP link, but we should already get an IPv6
|
||||
* address from pppd. Use that instead. We however do want to generate our
|
||||
* (own) IPv6 link local address, so return "link-local". */
|
||||
return NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -260,17 +258,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);
|
||||
NMDevicePpp *self = NM_DEVICE_PPP(device);
|
||||
|
||||
if (priv->ppp_manager) {
|
||||
nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL);
|
||||
g_clear_object(&priv->ppp_manager);
|
||||
}
|
||||
|
||||
g_clear_object(&priv->ip4_config);
|
||||
_ppp_mgr_cleanup(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_device_ppp_init(NMDevicePpp *self)
|
||||
{}
|
||||
|
|
@ -278,10 +272,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_mgr_cleanup(self);
|
||||
|
||||
G_OBJECT_CLASS(nm_device_ppp_parent_class)->dispose(object);
|
||||
}
|
||||
|
|
@ -306,7 +299,8 @@ 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->get_ip_method_auto = get_ip_method_auto;
|
||||
device_class->check_connection_compatible = check_connection_compatible;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->deactivate = deactivate;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
@ -21,12 +22,6 @@ enum NMActStageReturn {
|
|||
NM_ACT_STAGE_RETURN_FAILURE = 0, /* Hard failure of activation */
|
||||
NM_ACT_STAGE_RETURN_SUCCESS, /* Activation stage done */
|
||||
NM_ACT_STAGE_RETURN_POSTPONE, /* Long-running operation in progress */
|
||||
NM_ACT_STAGE_RETURN_IP_WAIT, /* IP config stage is waiting (state IP_WAIT) */
|
||||
NM_ACT_STAGE_RETURN_IP_DONE, /* IP config stage is done (state IP_DONE),
|
||||
* For the ip-config stage, this is similar to
|
||||
* NM_ACT_STAGE_RETURN_SUCCESS, except that no
|
||||
* IP config should be committed. */
|
||||
NM_ACT_STAGE_RETURN_IP_FAIL, /* IP config stage failed (state IP_FAIL), activation may proceed */
|
||||
};
|
||||
|
||||
#define NM_DEVICE_CAP_NONSTANDARD_CARRIER 0x80000000
|
||||
|
|
@ -34,8 +29,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 +37,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 +54,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 +70,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, reason);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
void nm_device_ip_method_dhcp4_start(NMDevice *self);
|
||||
|
||||
void nm_device_ip_method_autoconf6_start(NMDevice *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gint64 nm_device_get_configured_mtu_from_connection_default(NMDevice * self,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"), );
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -86,10 +85,10 @@ 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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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,11 +1626,11 @@ 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;
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
NMConnection * connection;
|
||||
NMSettingWireGuard * s_wg;
|
||||
guint n_peers;
|
||||
|
|
@ -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
|
||||
|
|
@ -1866,8 +1862,6 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne
|
|||
{
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
nm_device_set_dev2_ip_config(device, AF_INET, ip4_config);
|
||||
nm_device_set_dev2_ip_config(device, AF_INET6, ip6_config);
|
||||
l3cd_4 = _get_dev2_ip_config(self, AF_INET);
|
||||
l3cd_6 = _get_dev2_ip_config(self, AF_INET6);
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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"
|
||||
|
|
@ -71,8 +72,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"
|
||||
|
|
@ -344,15 +344,10 @@ 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 (*act_stage3_ip_config)(NMDevice *self, int addr_family);
|
||||
gboolean (*ready_for_ip_config)(NMDevice *self);
|
||||
|
||||
void (*ip4_config_pre_commit)(NMDevice *self, NMIP4Config *config);
|
||||
const char *(*get_ip_method_auto)(NMDevice *self, int addr_family);
|
||||
|
||||
/* Async deactivating (in the DEACTIVATING phase) */
|
||||
void (*deactivate_async)(NMDevice * self,
|
||||
|
|
@ -460,16 +455,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);
|
||||
|
||||
void nm_device_capture_initial_config(NMDevice *dev);
|
||||
const NML3ConfigData *nm_device_get_l3cd(NMDevice *self, gboolean get_commited);
|
||||
|
||||
void nm_device_l3cfg_commit(NMDevice *self, NML3CfgCommitType commit_type, gboolean commit_sync);
|
||||
|
||||
int nm_device_parent_get_ifindex(NMDevice *dev);
|
||||
NMDevice *nm_device_parent_get_device(NMDevice *dev);
|
||||
|
|
@ -547,7 +539,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);
|
||||
|
||||
|
|
@ -754,17 +746,11 @@ NMConnection *nm_device_new_default_connection(NMDevice *self);
|
|||
|
||||
const NMPObject *nm_device_get_best_default_route(NMDevice *self, int addr_family);
|
||||
|
||||
void nm_device_spawn_iface_helper(NMDevice *self);
|
||||
|
||||
gboolean nm_device_reapply(NMDevice *self, NMConnection *connection, GError **error);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -66,13 +66,16 @@ 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 gboolean
|
||||
ready_for_ip_config(NMDevice *device)
|
||||
{
|
||||
return NM_ACT_STAGE_RETURN_IP_FAIL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
{
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -154,7 +157,8 @@ 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->ready_for_ip_config = ready_for_ip_config;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
||||
|
|
|
|||
|
|
@ -124,14 +124,19 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink)
|
|||
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);
|
||||
nm_device_devip_set_failed(device, AF_INET, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||
nm_device_devip_set_failed(device, AF_INET6, 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_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||
nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||
nm_device_activate_schedule_stage3_ip_config(device, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_device_activate_schedule_stage2_device_config(device, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -188,31 +193,43 @@ set_platform_mtu(NMDevice *device, guint32 mtu)
|
|||
return NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class)->set_platform_mtu(device, mtu);
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip_config_start(NMDevice * device,
|
||||
int addr_family,
|
||||
gpointer * out_config,
|
||||
NMDeviceStateReason *out_failure_reason)
|
||||
static gboolean
|
||||
ready_for_ip_config(NMDevice *device)
|
||||
{
|
||||
return nm_device_get_ip_ifindex(device) > 0;
|
||||
}
|
||||
|
||||
static void
|
||||
act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
{
|
||||
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;
|
||||
if (!_is_internal_interface(device)) {
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME(l3cfg): we should create the IP ifindex before stage3 start.
|
||||
*
|
||||
* For now it's here because when the ovs-interface enters stage3, then it's added to the
|
||||
* controller (ovs-port) and the entry is create in the ovsdb. Only after that the kernel
|
||||
* link appears.
|
||||
*
|
||||
* This should change. */
|
||||
if (nm_device_get_ip_ifindex(device) <= 0) {
|
||||
_LOGT(LOGD_DEVICE, "waiting for link to appear");
|
||||
priv->waiting_for_interface = TRUE;
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nm_device_hw_addr_set_cloned(device, nm_device_get_applied_connection(device), FALSE)) {
|
||||
*out_failure_reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
nm_device_devip_set_failed(device, addr_family, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
return NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class)
|
||||
->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -443,7 +460,8 @@ 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_stage3_ip_config = act_stage3_ip_config;
|
||||
device_class->ready_for_ip_config = ready_for_ip_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;
|
||||
|
|
|
|||
|
|
@ -59,13 +59,16 @@ 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 gboolean
|
||||
ready_for_ip_config(NMDevice *device)
|
||||
{
|
||||
return NM_ACT_STAGE_RETURN_IP_FAIL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
{
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -186,7 +189,8 @@ 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->ready_for_ip_config = ready_for_ip_config;
|
||||
device_class->enslave_slave = enslave_slave;
|
||||
device_class->release_slave = release_slave;
|
||||
device_class->can_reapply_change_ovs_external_ids = TRUE;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
test_units = [
|
||||
'test-acd',
|
||||
'test-lldp',
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
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)) {
|
||||
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
|
||||
|
|
@ -1290,7 +1285,7 @@ nm_device_wifi_p2p_class_init(NMDeviceWifiP2PClass *klass)
|
|||
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_stage3_ip_config = act_stage3_ip_config;
|
||||
|
||||
device_class->deactivate = deactivate;
|
||||
device_class->unmanaged_on_quit = unmanaged_on_quit;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
@ -393,6 +394,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,
|
||||
|
|
@ -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;
|
||||
NMDeviceWifi * self = NM_DEVICE_WIFI(device);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self);
|
||||
const char * method;
|
||||
gboolean indicate_addressing_running;
|
||||
|
||||
connection = nm_device_get_applied_connection(device);
|
||||
if (priv->addressing_running_indicated)
|
||||
return;
|
||||
|
||||
method = nm_utils_get_ip_config_method(connection, addr_family);
|
||||
if (addr_family == AF_INET)
|
||||
/* 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(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;
|
||||
|
|
@ -3806,8 +3746,7 @@ nm_device_wifi_class_init(NMDeviceWifiClass *klass)
|
|||
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->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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -22,7 +21,6 @@ global:
|
|||
nm_modem_get_state;
|
||||
nm_modem_get_type;
|
||||
nm_modem_get_uid;
|
||||
nm_modem_ip4_pre_commit;
|
||||
nm_modem_is_claimed;
|
||||
nm_modem_manager_get;
|
||||
nm_modem_manager_get_modems;
|
||||
|
|
@ -32,8 +30,7 @@ global:
|
|||
nm_modem_manager_name_owner_unref;
|
||||
nm_modem_owns_port;
|
||||
nm_modem_set_mm_enabled;
|
||||
nm_modem_stage3_ip4_config_start;
|
||||
nm_modem_stage3_ip6_config_start;
|
||||
nm_modem_stage3_ip_config_start;
|
||||
nm_modem_state_to_string;
|
||||
nm_modem_unclaim;
|
||||
local:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -60,43 +61,9 @@ static void
|
|||
ppp_failed(NMModem *modem, guint i_reason, gpointer user_data)
|
||||
{
|
||||
NMDevice * device = NM_DEVICE(user_data);
|
||||
NMDeviceModem * self = NM_DEVICE_MODEM(user_data);
|
||||
NMDeviceStateReason reason = i_reason;
|
||||
|
||||
switch (nm_device_get_state(device)) {
|
||||
case NM_DEVICE_STATE_PREPARE:
|
||||
case NM_DEVICE_STATE_CONFIG:
|
||||
case NM_DEVICE_STATE_NEED_AUTH:
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason);
|
||||
break;
|
||||
case NM_DEVICE_STATE_IP_CONFIG:
|
||||
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);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -188,96 +155,39 @@ 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);
|
||||
|
||||
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_ip_method_failed(device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
|
||||
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,
|
||||
modem_new_config(NMModem * modem,
|
||||
int addr_family,
|
||||
const NML3ConfigData * l3cd,
|
||||
gboolean do_auto,
|
||||
const NMUtilsIPv6IfaceId *iid,
|
||||
int failure_reason_i,
|
||||
GError * error,
|
||||
gpointer user_data)
|
||||
{
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
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;
|
||||
gs_unref_object NMIP6Config *ignored = NULL;
|
||||
gboolean got_config = !!config;
|
||||
|
||||
if (!nm_device_activate_ip6_state_in_conf(device)) {
|
||||
_LOGD(LOGD_MB | LOGD_IP6,
|
||||
"retrieving IPv6 configuration while no longer in state IPv6 conf");
|
||||
return;
|
||||
}
|
||||
g_return_if_fail(nm_device_devip_get_state(device, addr_family) == NM_DEVICE_IP_STATE_PENDING);
|
||||
|
||||
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);
|
||||
_LOGW(LOGD_MB | LOGD_IP4, "retrieving IP configuration failed: %s", error->message);
|
||||
nm_device_devip_set_failed(device, addr_family, failure_reason_i);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Re-enable IPv6 on the interface */
|
||||
nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "0");
|
||||
if (!IS_IPv4)
|
||||
priv->iid = iid ? *iid : ((NMUtilsIPv6IfaceId) NM_UTILS_IPV6_IFACE_ID_INIT);
|
||||
|
||||
if (config)
|
||||
nm_device_set_dev2_ip_config(device, AF_INET6, NM_IP_CONFIG_CAST(config));
|
||||
|
||||
if (do_slaac == FALSE) {
|
||||
if (got_config)
|
||||
nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL);
|
||||
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);
|
||||
}
|
||||
return;
|
||||
if (do_auto) {
|
||||
if (IS_IPv4)
|
||||
nm_device_ip_method_dhcp4_start(device);
|
||||
else
|
||||
nm_device_ip_method_autoconf6_start(device);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
nm_assert(ignored == NULL);
|
||||
|
||||
switch (ret) {
|
||||
case NM_ACT_STAGE_RETURN_FAILURE:
|
||||
nm_device_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);
|
||||
break;
|
||||
case NM_ACT_STAGE_RETURN_POSTPONE:
|
||||
/* let SLAAC run */
|
||||
break;
|
||||
default:
|
||||
/* Should never get here since we've assured that the IPv6 method
|
||||
* will either be "auto" or "ignored" when starting IPv6 configuration.
|
||||
*/
|
||||
nm_assert_not_reached();
|
||||
}
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -606,36 +516,18 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
static NMActStageReturn
|
||||
act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
||||
{
|
||||
nm_modem_act_stage2_config(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem);
|
||||
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)
|
||||
{
|
||||
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device);
|
||||
gboolean autoip4 = FALSE;
|
||||
NMActStageReturn ret;
|
||||
|
||||
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;
|
||||
|
||||
return NM_DEVICE_CLASS(nm_device_modem_parent_class)
|
||||
->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
|
||||
return nm_modem_act_stage2_config(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem,
|
||||
device,
|
||||
out_failure_reason);
|
||||
}
|
||||
|
||||
static void
|
||||
ip4_config_pre_commit(NMDevice *device, NMIP4Config *config)
|
||||
act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
{
|
||||
nm_modem_ip4_pre_commit(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, device, config);
|
||||
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device);
|
||||
|
||||
if (nm_modem_stage3_ip_config_start(priv->modem, addr_family, device))
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -643,14 +535,15 @@ 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 +609,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 +796,7 @@ 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;
|
||||
device_class->get_enabled = get_enabled;
|
||||
device_class->set_enabled = set_enabled;
|
||||
device_class->owns_iface = owns_iface;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
@ -91,9 +90,6 @@ typedef struct {
|
|||
MMBearerIpConfig *ipv4_config;
|
||||
MMBearerIpConfig *ipv6_config;
|
||||
|
||||
guint idle_id_ip4;
|
||||
guint idle_id_ip6;
|
||||
|
||||
guint32 pin_tries;
|
||||
} NMModemBroadbandPrivate;
|
||||
|
||||
|
|
@ -958,29 +954,43 @@ set_mm_enabled(NMModem *_self, gboolean enabled)
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* IPv4 method static */
|
||||
|
||||
static gboolean
|
||||
static_stage3_ip4_done(NMModemBroadband *self)
|
||||
static void
|
||||
stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_method)
|
||||
{
|
||||
GError * error = NULL;
|
||||
gs_unref_object NMIP4Config *config = NULL;
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
NMModemBroadband * self = NM_MODEM_BROADBAND(modem);
|
||||
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;
|
||||
const char ** dns;
|
||||
guint i;
|
||||
gboolean do_auto = FALSE;
|
||||
int ifindex;
|
||||
NMUtilsIPv6IfaceId iid_data;
|
||||
const NMUtilsIPv6IfaceId *iid = NULL;
|
||||
|
||||
if (IS_IPv4) {
|
||||
g_return_if_fail(self->_priv.ipv4_config);
|
||||
g_return_if_fail(self->_priv.bearer);
|
||||
|
||||
if (ip_method == NM_MODEM_IP_METHOD_AUTO) {
|
||||
do_auto = TRUE;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
g_return_if_fail(self->_priv.ipv6_config);
|
||||
}
|
||||
|
||||
if (IS_IPv4) {
|
||||
guint32 address_network;
|
||||
guint32 gw = 0;
|
||||
NMPlatformIP4Address address;
|
||||
const char ** dns;
|
||||
guint i;
|
||||
guint32 ip4_route_table, ip4_route_metric;
|
||||
NMPlatformIP4Route * r;
|
||||
NMPlatformIP4Route route;
|
||||
guint32 mtu_n;
|
||||
|
||||
g_return_val_if_fail(self->_priv.ipv4_config, FALSE);
|
||||
g_return_val_if_fail(self->_priv.bearer, FALSE);
|
||||
|
||||
self->_priv.idle_id_ip4 = 0;
|
||||
const char * gw_string;
|
||||
|
||||
_LOGI("IPv4 static configuration:");
|
||||
|
||||
|
|
@ -988,8 +998,8 @@ 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,
|
||||
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)),
|
||||
|
|
@ -1000,8 +1010,8 @@ static_stage3_ip4_done(NMModemBroadband *self)
|
|||
/* 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,
|
||||
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)),
|
||||
|
|
@ -1010,36 +1020,50 @@ static_stage3_ip4_done(NMModemBroadband *self)
|
|||
}
|
||||
|
||||
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));
|
||||
g_return_if_fail(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,60 +1071,19 @@ 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;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
static_stage3_ip4_config_start(NMModem * modem,
|
||||
NMActRequest * req,
|
||||
NMDeviceStateReason *out_failure_reason)
|
||||
{
|
||||
NMModemBroadband * self = NM_MODEM_BROADBAND(modem);
|
||||
NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self);
|
||||
|
||||
/* 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);
|
||||
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* IPv6 method static */
|
||||
|
||||
static gboolean
|
||||
stage3_ip6_done(NMModemBroadband *self)
|
||||
{
|
||||
GError * error = NULL;
|
||||
NMIP6Config * config = NULL;
|
||||
const char * data_port;
|
||||
const char * address_string;
|
||||
} else {
|
||||
NMPlatformIP6Address address;
|
||||
NMModemIPMethod ip_method;
|
||||
const char ** dns;
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail(self->_priv.ipv6_config, FALSE);
|
||||
|
||||
self->_priv.idle_id_ip6 = 0;
|
||||
memset(&address, 0, sizeof(address));
|
||||
|
||||
ip_method = get_bearer_ip_method(self->_priv.ipv6_config);
|
||||
|
||||
address_string = mm_bearer_ip_config_get_address(self->_priv.ipv6_config);
|
||||
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,
|
||||
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)));
|
||||
|
|
@ -1108,9 +1091,11 @@ stage3_ip6_done(NMModemBroadband *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,
|
||||
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)),
|
||||
|
|
@ -1118,27 +1103,47 @@ stage3_ip6_done(NMModemBroadband *self)
|
|||
goto out;
|
||||
}
|
||||
|
||||
data_port = mm_bearer_get_interface(self->_priv.bearer);
|
||||
g_return_if_fail(data_port);
|
||||
|
||||
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:");
|
||||
|
||||
data_port = mm_bearer_get_interface(self->_priv.bearer);
|
||||
g_return_val_if_fail(data_port, FALSE);
|
||||
l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
|
||||
ifindex,
|
||||
NM_IP_CONFIG_SOURCE_WWAN);
|
||||
|
||||
config = nm_ip6_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
|
||||
nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port));
|
||||
do_auto = TRUE;
|
||||
|
||||
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_auto = 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_auto ? "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,
|
||||
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)),
|
||||
|
|
@ -1146,61 +1151,50 @@ stage3_ip6_done(NMModemBroadband *self)
|
|||
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,
|
||||
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_modem_emit_signal_new_config_failure(modem,
|
||||
addr_family,
|
||||
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE,
|
||||
error);
|
||||
return;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
stage3_ip6_config_request(NMModem *modem, NMDeviceStateReason *out_failure_reason)
|
||||
{
|
||||
NMModemBroadband * self = NM_MODEM_BROADBAND(modem);
|
||||
NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self);
|
||||
|
||||
/* 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);
|
||||
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
nm_modem_emit_signal_new_config_success(modem, addr_family, l3cd, do_auto, iid);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1564,27 +1558,24 @@ dispose(GObject *object)
|
|||
NMModemBroadband * self = NM_MODEM_BROADBAND(object);
|
||||
NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self);
|
||||
|
||||
nm_clear_g_source(&priv->idle_id_ip4);
|
||||
nm_clear_g_source(&priv->idle_id_ip6);
|
||||
|
||||
connect_context_clear(self);
|
||||
g_clear_object(&self->_priv.ipv4_config);
|
||||
g_clear_object(&self->_priv.ipv6_config);
|
||||
g_clear_object(&self->_priv.bearer);
|
||||
g_clear_object(&priv->ipv4_config);
|
||||
g_clear_object(&priv->ipv6_config);
|
||||
g_clear_object(&priv->bearer);
|
||||
|
||||
if (self->_priv.modem_iface) {
|
||||
g_signal_handlers_disconnect_by_data(self->_priv.modem_iface, self);
|
||||
g_clear_object(&self->_priv.modem_iface);
|
||||
if (priv->modem_iface) {
|
||||
g_signal_handlers_disconnect_by_data(priv->modem_iface, self);
|
||||
g_clear_object(&priv->modem_iface);
|
||||
}
|
||||
|
||||
if (self->_priv.modem_3gpp_iface) {
|
||||
g_signal_handlers_disconnect_by_data(self->_priv.modem_3gpp_iface, self);
|
||||
g_clear_object(&self->_priv.modem_3gpp_iface);
|
||||
if (priv->modem_3gpp_iface) {
|
||||
g_signal_handlers_disconnect_by_data(priv->modem_3gpp_iface, self);
|
||||
g_clear_object(&priv->modem_3gpp_iface);
|
||||
}
|
||||
|
||||
g_clear_object(&self->_priv.simple_iface);
|
||||
g_clear_object(&self->_priv.sim_iface);
|
||||
g_clear_object(&self->_priv.modem_object);
|
||||
g_clear_object(&priv->simple_iface);
|
||||
g_clear_object(&priv->sim_iface);
|
||||
g_clear_object(&priv->modem_object);
|
||||
|
||||
G_OBJECT_CLASS(nm_modem_broadband_parent_class)->dispose(object);
|
||||
}
|
||||
|
|
@ -1600,8 +1591,7 @@ nm_modem_broadband_class_init(NMModemBroadbandClass *klass)
|
|||
object_class->set_property = set_property;
|
||||
|
||||
modem_class->get_capabilities = get_capabilities;
|
||||
modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start;
|
||||
modem_class->stage3_ip6_config_request = stage3_ip6_config_request;
|
||||
modem_class->stage3_ip_config_start = stage3_ip_config_start;
|
||||
modem_class->disconnect = disconnect;
|
||||
modem_class->deactivate_cleanup = deactivate_cleanup;
|
||||
modem_class->set_mm_enabled = set_mm_enabled;
|
||||
|
|
|
|||
|
|
@ -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,48 @@ 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);
|
||||
}
|
||||
}
|
||||
gboolean any_good = FALSE;
|
||||
|
||||
if (iter == array) {
|
||||
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 (!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,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = 0,
|
||||
};
|
||||
|
||||
nm_ip4_config_add_route(priv->ip4_config, &mms_route, NULL);
|
||||
}
|
||||
} else {
|
||||
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),
|
||||
|
|
@ -912,30 +913,35 @@ context_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, g
|
|||
handle_settings(v_dict, user_data);
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
static_stage3_ip4_config_start(NMModem * modem,
|
||||
NMActRequest * req,
|
||||
NMDeviceStateReason *out_failure_reason)
|
||||
static void
|
||||
stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_method)
|
||||
{
|
||||
NMModemOfono * self = NM_MODEM_OFONO(modem);
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
|
||||
GError * error = NULL;
|
||||
|
||||
if (!priv->ip4_config) {
|
||||
_LOGD("IP4 config not ready(?)");
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
_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;
|
||||
if (!NM_IS_IPv4(addr_family) || ip_method == NM_MODEM_IP_METHOD_AUTO) {
|
||||
nm_modem_emit_signal_new_config_success(modem, addr_family, NULL, TRUE, NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!priv->l3cd_4) {
|
||||
nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "IP config not received");
|
||||
nm_modem_emit_signal_new_config_failure(modem,
|
||||
addr_family,
|
||||
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE,
|
||||
error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_modem_emit_signal_new_config_success(modem, addr_family, priv->l3cd_4, FALSE, NULL);
|
||||
|
||||
out:
|
||||
nm_modem_set_state(NM_MODEM(self),
|
||||
NM_MODEM_STATE_CONNECTED,
|
||||
nm_modem_state_to_string(NM_MODEM_STATE_CONNECTED));
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1040,7 +1046,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 +1264,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);
|
||||
|
|
@ -1301,5 +1307,5 @@ nm_modem_ofono_class_init(NMModemOfonoClass *klass)
|
|||
modem_class->check_connection_compatible_with_modem = check_connection_compatible_with_modem;
|
||||
|
||||
modem_class->modem_act_stage1_prepare = modem_act_stage1_prepare;
|
||||
modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start;
|
||||
modem_class->stage3_ip_config_start = stage3_ip_config_start;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -35,8 +35,7 @@
|
|||
#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_NEW_CONFIG "new-config"
|
||||
#define NM_MODEM_AUTH_REQUESTED "auth-requested"
|
||||
#define NM_MODEM_AUTH_RESULT "auth-result"
|
||||
#define NM_MODEM_REMOVED "removed"
|
||||
|
|
@ -124,15 +123,7 @@ typedef struct {
|
|||
NMConnection * connection,
|
||||
NMDeviceStateReason *out_failure_reason);
|
||||
|
||||
NMActStageReturn (*static_stage3_ip4_config_start)(NMModem * self,
|
||||
NMActRequest * req,
|
||||
NMDeviceStateReason *out_failure_reason);
|
||||
|
||||
/* Request the IP6 config; when the config returns the modem
|
||||
* subclass should emit the ip6_config_result signal.
|
||||
*/
|
||||
NMActStageReturn (*stage3_ip6_config_request)(NMModem * self,
|
||||
NMDeviceStateReason *out_failure_reason);
|
||||
void (*stage3_ip_config_start)(NMModem *self, int addr_family, NMModemIPMethod method);
|
||||
|
||||
void (*set_mm_enabled)(NMModem *self, gboolean enabled);
|
||||
|
||||
|
|
@ -161,7 +152,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,36 +178,15 @@ 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);
|
||||
|
||||
void nm_modem_act_stage2_config(NMModem *modem);
|
||||
|
||||
NMActStageReturn nm_modem_stage3_ip4_config_start(NMModem * modem,
|
||||
NMDevice * device,
|
||||
gboolean * out_autoip4,
|
||||
NMDeviceStateReason *out_failure_reason);
|
||||
|
||||
NMActStageReturn nm_modem_stage3_ip6_config_start(NMModem * modem,
|
||||
NMActStageReturn nm_modem_act_stage2_config(NMModem * self,
|
||||
NMDevice * device,
|
||||
NMDeviceStateReason *out_failure_reason);
|
||||
|
||||
void nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config);
|
||||
gboolean nm_modem_stage3_ip_config_start(NMModem *self, int addr_family, NMDevice *device);
|
||||
|
||||
void nm_modem_get_secrets(NMModem * modem,
|
||||
const char *setting_name,
|
||||
|
|
@ -249,6 +218,8 @@ NMModemIPType nm_modem_get_supported_ip_types(NMModem *self);
|
|||
/* For the modem-manager only */
|
||||
void nm_modem_emit_removed(NMModem *self);
|
||||
|
||||
void nm_modem_emit_auth_requested(NMModem *self);
|
||||
|
||||
void nm_modem_emit_prepare_result(NMModem *self, gboolean success, NMDeviceStateReason reason);
|
||||
|
||||
void nm_modem_emit_ppp_failed(NMModem *self, NMDeviceStateReason reason);
|
||||
|
|
@ -256,7 +227,23 @@ 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,
|
||||
NMDeviceStateReason failure_reason,
|
||||
GError * error);
|
||||
void nm_modem_emit_signal_new_config_success(NMModem * self,
|
||||
int addr_family,
|
||||
const NML3ConfigData * l3cd,
|
||||
gboolean do_auto,
|
||||
const NMUtilsIPv6IfaceId *iid);
|
||||
void nm_modem_emit_signal_new_config_failure(NMModem * self,
|
||||
int addr_family,
|
||||
NMDeviceStateReason failure_reason,
|
||||
GError * error);
|
||||
|
||||
const char *nm_modem_ip_type_to_string(NMModemIPType ip_type);
|
||||
|
||||
|
|
|
|||
103
src/core/dhcp/README.next.md
Normal file
103
src/core/dhcp/README.next.md
Normal file
|
|
@ -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.
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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,123 @@ 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 {
|
||||
/* 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 +205,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, const struct in6_addr *ll_addr, GError **error);
|
||||
|
||||
void (*stop)(NMDhcpClient *self, gboolean release);
|
||||
|
||||
|
|
@ -128,64 +229,25 @@ typedef struct {
|
|||
|
||||
GType nm_dhcp_client_get_type(void);
|
||||
|
||||
struct _NMDedupMultiIndex *nm_dhcp_client_get_multi_idx(NMDhcpClient *self);
|
||||
gboolean nm_dhcp_client_start_ip4(NMDhcpClient *self, GError **error);
|
||||
gboolean nm_dhcp_client_start_ip6(NMDhcpClient *self, GError **error);
|
||||
|
||||
const NMDhcpClientConfig *nm_dhcp_client_get_config(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);
|
||||
|
||||
guint32 nm_dhcp_client_get_route_metric(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);
|
||||
|
||||
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 +267,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 +277,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
|
||||
*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -333,14 +333,13 @@ 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;
|
||||
gs_free_error GError * local = NULL;
|
||||
const char * iface;
|
||||
const char * uuid;
|
||||
const char * system_bus_address;
|
||||
|
|
@ -350,9 +349,12 @@ dhclient_start(NMDhcpClient *client,
|
|||
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);
|
||||
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,28 +513,27 @@ 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;
|
||||
gs_unref_bytes GBytes * new_client_id = NULL;
|
||||
const NMDhcpClientConfig *client_config;
|
||||
|
||||
client_id = nm_dhcp_client_get_client_id(client);
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
|
||||
priv->conf_file = create_dhclient_config(
|
||||
self,
|
||||
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),
|
||||
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,
|
||||
|
|
@ -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, const struct in6_addr *ll_addr, GError **error)
|
||||
{
|
||||
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
|
||||
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
|
||||
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));
|
||||
}
|
||||
|
|
@ -636,15 +626,18 @@ static GBytes *
|
|||
get_duid(NMDhcpClient *client)
|
||||
{
|
||||
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
|
||||
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
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)));
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -527,12 +265,6 @@ nm_dhcp_manager_init(NMDhcpManager *self)
|
|||
NM_CONFIG_KEYFILE_KEY_MAIN_DHCP,
|
||||
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
|
||||
client = client_free;
|
||||
if (nm_config_get_configure_and_quit(config) == NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED) {
|
||||
client_factory = &_nm_dhcp_client_factory_internal;
|
||||
if (client && !nm_streq(client, client_factory->name))
|
||||
nm_log_info(LOGD_DHCP,
|
||||
"dhcp-init: Using internal DHCP client since configure-and-quit is set.");
|
||||
} else {
|
||||
if (client) {
|
||||
client_factory = _client_factory_available(_client_factory_find_by_name(client));
|
||||
if (!client_factory)
|
||||
|
|
@ -559,7 +291,6 @@ nm_dhcp_manager_init(NMDhcpManager *self)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_return_if_fail(client_factory);
|
||||
|
||||
|
|
@ -572,21 +303,6 @@ nm_dhcp_manager_init(NMDhcpManager *self)
|
|||
priv->client_factory = client_factory;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,7 +257,7 @@ lease_parse_address(NDhcp4ClientLease *lease,
|
|||
a_next_server.s_addr);
|
||||
}
|
||||
|
||||
nm_ip4_config_add_address(ip4_config,
|
||||
nm_l3_config_data_add_address_4(l3cd,
|
||||
&((const NMPlatformIP4Address){
|
||||
.address = a_address.s_addr,
|
||||
.peer_address = a_address.s_addr,
|
||||
|
|
@ -272,7 +273,7 @@ lease_parse_address(NDhcp4ClientLease *lease,
|
|||
|
||||
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];
|
||||
|
|
@ -338,7 +337,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
|||
guint32 m;
|
||||
gboolean has_router_from_classless = FALSE;
|
||||
gboolean has_classless = FALSE;
|
||||
guint32 default_route_metric = route_metric;
|
||||
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;
|
||||
}
|
||||
} else
|
||||
m = 0;
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
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,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
}),
|
||||
NULL);
|
||||
}));
|
||||
}
|
||||
|
||||
has_classless = TRUE;
|
||||
|
|
@ -419,17 +414,17 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
|||
continue;
|
||||
}
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((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);
|
||||
.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++;
|
||||
m = default_route_metric_offset++;
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.gateway = gateway,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
}),
|
||||
NULL);
|
||||
}));
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
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,
|
||||
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,
|
||||
l_data,
|
||||
l_data_len);
|
||||
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;
|
||||
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)),
|
||||
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,
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
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);
|
||||
NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
|
||||
const NMDhcpClientConfig *client_config;
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,17 +69,14 @@ 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;
|
||||
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];
|
||||
|
|
@ -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,7 +155,7 @@ 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,
|
||||
nm_l3_config_data_add_address_4(l3cd,
|
||||
&((const NMPlatformIP4Address){
|
||||
.address = a_address.s_addr,
|
||||
.peer_address = a_address.s_addr,
|
||||
|
|
@ -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) {
|
||||
|
|
@ -235,7 +230,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
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;
|
||||
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;
|
||||
m = 0;
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
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_coerced = nm_platform_route_table_coerce(route_table),
|
||||
}),
|
||||
NULL);
|
||||
.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++;
|
||||
m = default_route_metric_offset++;
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.gateway = a_router[i].s_addr,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
}),
|
||||
NULL);
|
||||
}));
|
||||
}
|
||||
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,
|
||||
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,
|
||||
l_data,
|
||||
l_data_len);
|
||||
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,37 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
static void
|
||||
bound4_handle(NMDhcpSystemd *self, gboolean extended)
|
||||
{
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
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;
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = 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)),
|
||||
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,
|
||||
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) {
|
||||
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 +517,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 +553,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);
|
||||
const NMDhcpClientConfig * client_config;
|
||||
gs_free char * lease_file = NULL;
|
||||
GBytes * hwaddr;
|
||||
const uint8_t * hwaddr_arr;
|
||||
|
|
@ -584,6 +580,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 +598,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 +606,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 +631,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 +645,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 +656,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 +691,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 +704,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 +713,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 +742,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,17 +756,16 @@ 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;
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
struct in6_addr tmp_addr;
|
||||
const struct in6_addr * dns;
|
||||
|
|
@ -778,13 +774,14 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
|
|||
char ** domains;
|
||||
const char * s;
|
||||
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 +795,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)
|
||||
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) {
|
||||
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 && !has_any_addresses) {
|
||||
g_set_error_literal(error,
|
||||
NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_FAILED,
|
||||
|
|
@ -820,7 +821,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 +831,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 +840,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);
|
||||
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;
|
||||
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)),
|
||||
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,
|
||||
NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
|
||||
NM_DHCP_CLIENT_FLAGS_INFO_ONLY),
|
||||
&options,
|
||||
client_config->v6.info_only,
|
||||
ts,
|
||||
&error);
|
||||
|
||||
if (!ip6_config) {
|
||||
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 +906,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 +923,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, const struct in6_addr *ll_addr, 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 +939,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 +957,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 +999,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 +1008,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 */
|
||||
|
|
@ -1029,7 +1026,7 @@ ip6_start(NMDhcpClient * client,
|
|||
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");
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -26,9 +27,7 @@
|
|||
static gboolean
|
||||
ip4_process_dhcpcd_rfc3442_routes(const char * iface,
|
||||
const char * str,
|
||||
guint32 route_table,
|
||||
guint32 route_metric,
|
||||
NMIP4Config *ip4_config,
|
||||
NML3ConfigData *l3cd,
|
||||
guint32 * gwaddr)
|
||||
{
|
||||
gs_free const char **routes = NULL;
|
||||
|
|
@ -46,7 +45,6 @@ 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;
|
||||
|
||||
|
|
@ -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,
|
||||
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,9 +157,7 @@ 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,
|
||||
NML3ConfigData *l3cd,
|
||||
guint32 * gwaddr)
|
||||
{
|
||||
gs_free const char **octets = NULL;
|
||||
|
|
@ -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,
|
||||
|
|
@ -208,15 +211,13 @@ 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,
|
||||
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,25 +371,17 @@ 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;
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
guint32 tmp_addr;
|
||||
in_addr_t addr;
|
||||
NMPlatformIP4Address address;
|
||||
|
|
@ -406,19 +390,24 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
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;
|
||||
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
|
||||
|
|
|
|||
|
|
@ -8,17 +8,14 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "nm-ip4-config.h"
|
||||
#include "nm-ip6-config.h"
|
||||
#include "nm-l3-config-data.h"
|
||||
|
||||
NMIP4Config *nm_dhcp_utils_ip4_config_from_options(struct _NMDedupMultiIndex *multi_idx,
|
||||
NML3ConfigData *nm_dhcp_utils_ip4_config_from_options(struct _NMDedupMultiIndex *multi_idx,
|
||||
int ifindex,
|
||||
const char * iface,
|
||||
GHashTable * options,
|
||||
guint32 route_table,
|
||||
guint32 route_metric);
|
||||
GHashTable * options);
|
||||
|
||||
NMIP6Config *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
|
||||
NML3ConfigData *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
|
||||
int ifindex,
|
||||
const char * iface,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
NML3ConfigData * l3cd;
|
||||
|
||||
config = nm_dhcp_utils_ip4_config_from_options(multi_idx,
|
||||
ifindex,
|
||||
iface,
|
||||
options,
|
||||
RT_TABLE_MAIN,
|
||||
route_metric);
|
||||
g_assert(config);
|
||||
return config;
|
||||
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,8 +72,8 @@ static const Option generic_options[] = {
|
|||
static void
|
||||
test_generic_options(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const NMPlatformIP4Address * address;
|
||||
const NMPlatformIP4Route * route;
|
||||
guint32 tmp;
|
||||
|
|
@ -89,43 +87,42 @@ test_generic_options(void)
|
|||
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);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
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(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;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = 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"},
|
||||
{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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
g_assert(nm_l3_config_data_get_metered(l3cd) == TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -252,7 +243,7 @@ test_parse_search_list(void)
|
|||
}
|
||||
|
||||
static void
|
||||
ip4_test_route(NMIP4Config *ip4_config,
|
||||
ip4_test_route(const NML3ConfigData *l3cd,
|
||||
guint route_num,
|
||||
const char * expected_dest,
|
||||
const char * expected_gw,
|
||||
|
|
@ -263,7 +254,7 @@ ip4_test_route(NMIP4Config *ip4_config,
|
|||
|
||||
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,21 +263,23 @@ 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;
|
||||
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";
|
||||
|
|
@ -298,22 +291,20 @@ test_classless_static_routes_1(void)
|
|||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
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;
|
||||
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";
|
||||
|
|
@ -325,22 +316,20 @@ test_classless_static_routes_2(void)
|
|||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
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;
|
||||
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";
|
||||
|
|
@ -354,25 +343,22 @@ test_fedora_dhclient_classless_static_routes(void)
|
|||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
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;
|
||||
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[] = {
|
||||
|
|
@ -384,22 +370,20 @@ 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;
|
||||
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";
|
||||
|
|
@ -413,25 +397,23 @@ 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;
|
||||
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";
|
||||
|
|
@ -444,25 +426,23 @@ 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;
|
||||
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";
|
||||
|
|
@ -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,19 +463,17 @@ 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;
|
||||
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[] = {
|
||||
|
|
@ -506,22 +484,20 @@ 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;
|
||||
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[] = {
|
||||
|
|
@ -532,22 +508,20 @@ 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;
|
||||
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";
|
||||
|
|
@ -557,24 +531,21 @@ test_dhclient_gw_in_classless_routes(void)
|
|||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
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);
|
||||
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);
|
||||
|
||||
/* Gateway */
|
||||
ip4_test_gateway(ip4_config, expected_gateway);
|
||||
|
||||
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;
|
||||
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";
|
||||
|
|
@ -584,81 +555,77 @@ test_dhcpcd_gw_in_classless_routes(void)
|
|||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
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);
|
||||
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);
|
||||
|
||||
/* Gateway */
|
||||
ip4_test_gateway(ip4_config, expected_gateway);
|
||||
|
||||
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;
|
||||
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);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
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,8 +649,8 @@ test_ip4_missing_prefix_8(void)
|
|||
static void
|
||||
test_ip4_prefix_classless(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
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
|
||||
|
|
@ -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) \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
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);
|
||||
c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_data_lst_head,
|
||||
&ip_data->ip_data_lst);
|
||||
|
||||
/* We also need to set priv->ip_config_lst_need_sort, but the caller will do that! */
|
||||
|
||||
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
|
||||
|
|
@ -431,27 +421,32 @@ add_dns_option_item(GPtrArray *array, const char *str)
|
|||
|
||||
static void
|
||||
add_dns_domains(GPtrArray * array,
|
||||
const NMIPConfig *ip_config,
|
||||
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;
|
||||
gconstpointer nameservers;
|
||||
const char *const *strv;
|
||||
|
||||
addr_family = nm_ip_config_get_addr_family(ip_config);
|
||||
nm_assert(ifindex == nm_l3_config_data_get_ifindex(l3cd));
|
||||
|
||||
nm_assert_addr_family(addr_family);
|
||||
nm_assert(ifindex > 0);
|
||||
nm_assert(ifindex == nm_ip_config_get_ifindex(ip_config));
|
||||
|
||||
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;
|
||||
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);
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
char ** strv;
|
||||
GPtrArray * domains;
|
||||
NMDedupMultiIter ipconf_iter;
|
||||
const NMPlatformIPAddress *address;
|
||||
const NMPlatformIPRoute * route;
|
||||
|
||||
nm_assert_addr_family(addr_family);
|
||||
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;
|
||||
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,10 +1417,11 @@ _mgr_configs_data_construct(NMDnsManager *self)
|
|||
}
|
||||
}
|
||||
|
||||
c_list_for_each_entry (ip_data, head, ip_config_lst) {
|
||||
NMIPConfig * ip_config = ip_data->ip_config;
|
||||
c_list_for_each_entry (ip_data, head, ip_data_lst) {
|
||||
int priority;
|
||||
const char **domains;
|
||||
const char ** domains;
|
||||
const char *const *strv_searches;
|
||||
const char *const *strv_domains;
|
||||
guint n_searches;
|
||||
guint n_domains;
|
||||
guint num_dom1;
|
||||
|
|
@ -1450,16 +1431,19 @@ _mgr_configs_data_construct(NMDnsManager *self)
|
|||
gboolean has_default_route_maybe = FALSE;
|
||||
gboolean has_default_route_explicit = FALSE;
|
||||
gboolean has_default_route_auto = 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;
|
||||
|
||||
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);
|
||||
|
|
@ -1579,7 +1563,7 @@ _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.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)
|
||||
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);
|
||||
|
||||
ifindex = nm_ip_config_get_ifindex(ip_config);
|
||||
g_return_val_if_fail(ifindex > 0, 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;
|
||||
}
|
||||
|
||||
nm_assert_addr_family(addr_family);
|
||||
|
||||
priv = NM_DNS_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
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 (!data)
|
||||
ip_data = NULL;
|
||||
else
|
||||
ip_data = _dns_config_data_find_ip_config(data, ip_config);
|
||||
|
||||
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;
|
||||
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 i, num;
|
||||
const int addr_family = nm_ip_config_get_addr_family(ip_config);
|
||||
guint num;
|
||||
guint num_domains;
|
||||
guint num_searches;
|
||||
guint i;
|
||||
char buf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
const NMIPAddr * addr;
|
||||
const char * ifname;
|
||||
gconstpointer nameservers;
|
||||
|
||||
num = nm_ip_config_get_num_nameservers(ip_config);
|
||||
if (!num)
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -98,8 +99,11 @@ 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);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -246,40 +245,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;
|
||||
guint n;
|
||||
guint i;
|
||||
gboolean is_routing;
|
||||
const char *domain;
|
||||
const char * domain;
|
||||
gboolean has_config = FALSE;
|
||||
gconstpointer nameservers;
|
||||
|
||||
addr_family = nm_ip_config_get_addr_family(data->ip_config);
|
||||
addr_size = nm_utils_addr_family_to_size(addr_family);
|
||||
addr_size = nm_utils_addr_family_to_size(ip_data->addr_family);
|
||||
|
||||
if ((!data->domains.search || !data->domains.search[0])
|
||||
&& !data->domains.has_default_route_exclusive && !data->domains.has_default_route)
|
||||
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;
|
||||
}
|
||||
|
|
@ -321,19 +322,17 @@ 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)));
|
||||
dns_over_tls =
|
||||
NM_MAX(dns_over_tls, nm_ip4_config_dns_over_tls_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));
|
||||
dns_over_tls = NM_MAX(dns_over_tls, nm_l3_config_data_get_dns_over_tls(ip_data->l3cd));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -551,7 +550,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)
|
||||
{
|
||||
|
|
@ -569,11 +568,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) {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -86,7 +87,7 @@ dm_watch_cb(GPid pid, int status, gpointer user_data)
|
|||
|
||||
static GPtrArray *
|
||||
create_dm_cmd_line(const char * iface,
|
||||
const NMIP4Config *ip4_config,
|
||||
const NML3ConfigData *l3cd,
|
||||
const char * pidfile,
|
||||
gboolean announce_android_metered,
|
||||
GError ** error)
|
||||
|
|
@ -96,13 +97,17 @@ create_dm_cmd_line(const char * iface,
|
|||
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,
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,8 +33,8 @@ 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 nm_dnsmasq_manager_start(NMDnsMasqManager * manager,
|
||||
const NML3ConfigData *l3cd,
|
||||
gboolean announce_android_metered,
|
||||
GError ** error);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@ gboolean nm_main_utils_early_setup(const char * progname,
|
|||
gpointer option_context_hook_data,
|
||||
const char *summary);
|
||||
|
||||
/* The following functions are not implemented inside nm-main-utils.c, instead
|
||||
* main.c and nm-iface-helper.c */
|
||||
|
||||
void nm_main_config_reload(int signal);
|
||||
|
||||
#endif /* __MAIN_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -269,16 +269,6 @@ _dbus_manager_init(NMConfig *config)
|
|||
if (c_a_q_type == NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED)
|
||||
return nm_dbus_manager_acquire_bus(busmgr, TRUE);
|
||||
|
||||
if (c_a_q_type == NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED) {
|
||||
/* D-Bus is useless in configure and quit mode -- we're eventually dropping
|
||||
* off and potential clients would have no way of knowing whether we're
|
||||
* finished already or didn't start yet.
|
||||
*
|
||||
* But we still create a nm_dbus_manager_get_dbus_connection() D-Bus connection
|
||||
* so that we can talk to other services like firewalld. */
|
||||
return nm_dbus_manager_acquire_bus(busmgr, FALSE);
|
||||
}
|
||||
|
||||
nm_assert(c_a_q_type == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD);
|
||||
/* in initrd we don't have D-Bus at all. Don't even try to get the G_BUS_TYPE_SYSTEM
|
||||
* connection. And of course don't claim the D-Bus name. */
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
@ -130,9 +127,10 @@ libNetworkManager = static_library(
|
|||
'dnsmasq/nm-dnsmasq-manager.c',
|
||||
'dnsmasq/nm-dnsmasq-utils.c',
|
||||
'ppp/nm-ppp-manager-call.c',
|
||||
'settings/plugins/keyfile/nms-keyfile-storage.c',
|
||||
'ppp/nm-ppp-mgr.c',
|
||||
'settings/plugins/keyfile/nms-keyfile-plugin.c',
|
||||
'settings/plugins/keyfile/nms-keyfile-reader.c',
|
||||
'settings/plugins/keyfile/nms-keyfile-storage.c',
|
||||
'settings/plugins/keyfile/nms-keyfile-utils.c',
|
||||
'settings/plugins/keyfile/nms-keyfile-writer.c',
|
||||
'settings/nm-agent-manager.c',
|
||||
|
|
@ -169,7 +167,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',
|
||||
|
|
@ -183,40 +180,6 @@ libNetworkManager = static_library(
|
|||
],
|
||||
)
|
||||
|
||||
executable(
|
||||
'nm-iface-helper',
|
||||
'nm-iface-helper.c',
|
||||
dependencies: [
|
||||
core_default_dep,
|
||||
glib_dep,
|
||||
libudev_dep,
|
||||
libndp_dep,
|
||||
dl_dep,
|
||||
],
|
||||
link_with: [
|
||||
libNetworkManagerBase,
|
||||
libnm_core_aux_intern,
|
||||
libnm_core_impl,
|
||||
libnm_crypto,
|
||||
libnm_systemd_core,
|
||||
libnm_platform,
|
||||
libnm_systemd_shared,
|
||||
libnm_base,
|
||||
libnm_udev_aux,
|
||||
libnm_log_core,
|
||||
libnm_glib_aux,
|
||||
libnm_std_aux,
|
||||
libn_acd,
|
||||
libn_dhcp4,
|
||||
libc_rbtree,
|
||||
libc_siphash,
|
||||
],
|
||||
link_args: ldflags_linker_script_binary,
|
||||
link_depends: linker_script_binary,
|
||||
install: true,
|
||||
install_dir: nm_libexecdir,
|
||||
)
|
||||
|
||||
if enable_tests
|
||||
test_c_flags = []
|
||||
if require_root_tests
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
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,6 +721,7 @@ 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;
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
@ -38,6 +39,8 @@ struct _NMNDiscPrivate {
|
|||
/* this *must* be the first field. */
|
||||
NMNDiscDataInternal rdata;
|
||||
|
||||
const NML3ConfigData *l3cd;
|
||||
|
||||
char *last_error;
|
||||
|
||||
GSource *ra_timeout_source;
|
||||
|
|
@ -55,37 +58,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;
|
||||
/* immutable values from here on: */
|
||||
|
||||
NMPlatform *platform;
|
||||
NMPNetns * netns;
|
||||
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};
|
||||
|
||||
|
|
@ -114,15 +105,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();
|
||||
|
||||
|
|
@ -130,20 +116,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;
|
||||
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;
|
||||
|
||||
for (i = 0; i < rdata->addresses_n; i++) {
|
||||
const NMNDiscAddress *ndisc_addr = &rdata->addresses[i];
|
||||
|
|
@ -152,7 +129,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,
|
||||
|
|
@ -178,8 +155,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);
|
||||
|
|
@ -188,12 +167,13 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
|
|||
}
|
||||
|
||||
if (rdata->gateways_n > 0) {
|
||||
const NMIcmpv6RouterPref first_pref = rdata->gateways[0].preference;
|
||||
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++) {
|
||||
|
|
@ -201,13 +181,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -315,7 +288,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 *
|
||||
|
|
@ -323,7 +296,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
|
||||
|
|
@ -331,7 +304,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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -391,15 +364,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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -479,11 +463,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",
|
||||
|
|
@ -608,7 +592,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)
|
||||
|
|
@ -899,7 +883,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;
|
||||
|
|
@ -997,30 +981,82 @@ 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;
|
||||
const struct in6_addr *in6arr;
|
||||
const char *const * strvarr;
|
||||
NMDedupMultiIter iter;
|
||||
const NMPObject * obj;
|
||||
guint len;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < addresses->len; i++) {
|
||||
if (nm_ndisc_add_address(ndisc, &g_array_index(addresses, NMNDiscAddress, i), 0, FALSE))
|
||||
nm_assert(NM_IS_NDISC(ndisc));
|
||||
nm_assert(nm_ndisc_get_node_type(ndisc) == NM_NDISC_NODE_TYPE_ROUTER);
|
||||
|
||||
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;
|
||||
|
||||
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, 0, 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;
|
||||
}
|
||||
|
||||
|
|
@ -1061,7 +1097,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) {
|
||||
|
|
@ -1100,26 +1136,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);
|
||||
|
|
@ -1129,8 +1165,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);
|
||||
}
|
||||
|
||||
|
|
@ -1147,7 +1183,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;
|
||||
|
|
@ -1374,7 +1410,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;
|
||||
}
|
||||
|
||||
|
|
@ -1699,86 +1735,88 @@ 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;
|
||||
|
|
@ -1828,9 +1866,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);
|
||||
|
|
@ -1838,7 +1873,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);
|
||||
}
|
||||
|
|
@ -1854,89 +1892,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,
|
||||
obj_properties[PROP_CONFIG] =
|
||||
g_param_spec_pointer(NM_NDISC_CONFIG,
|
||||
"",
|
||||
"",
|
||||
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);
|
||||
|
||||
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
|
||||
signals[CONFIG_RECEIVED] = g_signal_new(NM_NDISC_CONFIG_RECEIVED,
|
||||
|
|
@ -1947,9 +1908,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,
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
gs_unref_object NML3Cfg *l3cfg = NULL;
|
||||
NMNDisc * ndisc;
|
||||
const int ifindex = 1;
|
||||
const char * ifname = nm_platform_link_get_name(NM_PLATFORM_GET, ifindex);
|
||||
NMUtilsIPv6IfaceId iid = {};
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
|
||||
ndisc = nm_fake_ndisc_new(ifindex, ifname);
|
||||
l3cfg = nm_netns_l3cfg_acquire(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);
|
||||
|
|
@ -343,11 +360,12 @@ test_everything(void)
|
|||
|
||||
static void
|
||||
test_preference_order_cb(NMNDisc * ndisc,
|
||||
const NMNDiscData *rdata,
|
||||
guint changed_int,
|
||||
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,
|
||||
|
|
@ -435,11 +453,12 @@ test_preference_order(void)
|
|||
|
||||
static void
|
||||
test_preference_changed_cb(NMNDisc * ndisc,
|
||||
const NMNDiscData *rdata,
|
||||
guint changed_int,
|
||||
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,
|
||||
|
|
@ -577,8 +596,9 @@ test_preference_changed(void)
|
|||
|
||||
static void
|
||||
_test_dns_solicit_loop_changed(NMNDisc * ndisc,
|
||||
const NMNDiscData *rdata,
|
||||
guint changed_int,
|
||||
const NMNDiscData * rdata,
|
||||
guint changed_i,
|
||||
const NML3ConfigData *l3cd,
|
||||
TestData * data)
|
||||
{
|
||||
data->counter++;
|
||||
|
|
|
|||
|
|
@ -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,6 +21,8 @@ NMTST_DEFINE();
|
|||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
gs_unref_object NML3Cfg *l3cfg = NULL;
|
||||
NMNDiscConfig config;
|
||||
GMainLoop * loop;
|
||||
NMNDisc * ndisc;
|
||||
int ifindex = 1;
|
||||
|
|
@ -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_l3cfg_acquire(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);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
typedef struct {
|
||||
CList call_ids_lst_head;
|
||||
NMFirewallConfig *firewall_config;
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -264,7 +264,9 @@ 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);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -529,7 +529,7 @@ nm_config_cmd_line_options_free(NMConfigCmdLineOptions *cli)
|
|||
static NMConfigConfigureAndQuitType
|
||||
string_to_configure_and_quit(const char *value, GError **error)
|
||||
{
|
||||
NMConfigConfigureAndQuitType ret;
|
||||
int v_bool;
|
||||
|
||||
if (value == NULL)
|
||||
return NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED;
|
||||
|
|
@ -537,11 +537,18 @@ string_to_configure_and_quit(const char *value, GError **error)
|
|||
if (nm_streq(value, "initrd"))
|
||||
return NM_CONFIG_CONFIGURE_AND_QUIT_INITRD;
|
||||
|
||||
ret = nm_config_parse_boolean(value, NM_CONFIG_CONFIGURE_AND_QUIT_INVALID);
|
||||
if (ret == NM_CONFIG_CONFIGURE_AND_QUIT_INVALID)
|
||||
g_set_error(error, 1, 0, N_("'%s' is not valid"), value);
|
||||
v_bool = nm_config_parse_boolean(value, -1);
|
||||
if (v_bool == -1) {
|
||||
nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, N_("'%s' is not valid"), value);
|
||||
return NM_CONFIG_CONFIGURE_AND_QUIT_INVALID;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (v_bool) {
|
||||
_LOGW("'[main].configure-and-quit=1' in \"NetworkManager.conf\" is no longer implemented "
|
||||
"and has no effect");
|
||||
}
|
||||
|
||||
return NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -552,11 +559,7 @@ parse_configure_and_quit(const char *option_name,
|
|||
{
|
||||
NMConfigCmdLineOptions *cli = user_data;
|
||||
|
||||
if (value == NULL)
|
||||
cli->configure_and_quit = NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED;
|
||||
else
|
||||
cli->configure_and_quit = string_to_configure_and_quit(value, error);
|
||||
|
||||
if (cli->configure_and_quit == NM_CONFIG_CONFIGURE_AND_QUIT_INVALID) {
|
||||
g_prefix_error(error, N_("Bad '%s' option: "), option_name);
|
||||
return FALSE;
|
||||
|
|
@ -1383,16 +1386,13 @@ read_entire_config(const NMConfigCmdLineOptions *cli,
|
|||
|
||||
switch (cli->configure_and_quit) {
|
||||
case NM_CONFIG_CONFIGURE_AND_QUIT_INVALID:
|
||||
g_assert_not_reached();
|
||||
nm_assert_not_reached();
|
||||
break;
|
||||
case NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED:
|
||||
/* do nothing */
|
||||
break;
|
||||
case NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED:
|
||||
g_key_file_set_boolean(keyfile,
|
||||
g_key_file_set_string(keyfile,
|
||||
NM_CONFIG_KEYFILE_GROUP_MAIN,
|
||||
"configure-and-quit",
|
||||
TRUE);
|
||||
"no");
|
||||
break;
|
||||
case NM_CONFIG_CONFIGURE_AND_QUIT_INITRD:
|
||||
g_key_file_set_string(keyfile,
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ typedef enum {
|
|||
typedef enum {
|
||||
NM_CONFIG_CONFIGURE_AND_QUIT_INVALID = -1,
|
||||
NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED = FALSE,
|
||||
NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED = TRUE,
|
||||
NM_CONFIG_CONFIGURE_AND_QUIT_INITRD,
|
||||
NM_CONFIG_CONFIGURE_AND_QUIT_INITRD = 2,
|
||||
} NMConfigConfigureAndQuitType;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
nm_dhcp_config_set_options(NMDhcpConfig *self, GHashTable *options)
|
||||
static GVariant *
|
||||
_l3cd_to_options(const NML3ConfigData *l3cd, int addr_family)
|
||||
{
|
||||
NMDhcpConfigPrivate *priv;
|
||||
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_lease(NMDhcpConfig *self, const NML3ConfigData *l3cd)
|
||||
{
|
||||
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,
|
||||
"",
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
const NMPObject * obj;
|
||||
GVariantBuilder int_builder;
|
||||
NMDedupMultiIter ipconf_iter;
|
||||
GVariant * var1;
|
||||
GVariant * var2;
|
||||
guint n;
|
||||
guint i;
|
||||
const NMPObject *default_route;
|
||||
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,
|
||||
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))) {
|
||||
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,
|
||||
nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
|
||||
l3cd,
|
||||
&obj,
|
||||
NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))) {
|
||||
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,9 +289,7 @@ fill_device_props(NMDevice * device,
|
|||
GVariant ** dhcp4_props,
|
||||
GVariant ** dhcp6_props)
|
||||
{
|
||||
NMProxyConfig *proxy_config;
|
||||
NMIP4Config * ip4_config;
|
||||
NMIP6Config * ip6_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 */
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1,857 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "src/core/nm-default-daemon.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "libnm-glib-aux/nm-c-list.h"
|
||||
|
||||
#include "main-utils.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "libnm-platform/nm-linux-platform.h"
|
||||
#include "libnm-platform/nm-platform-utils.h"
|
||||
#include "dhcp/nm-dhcp-manager.h"
|
||||
#include "ndisc/nm-ndisc.h"
|
||||
#include "ndisc/nm-lndp-ndisc.h"
|
||||
#include "nm-utils.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "nm-setting-ip6-config.h"
|
||||
#include "libnm-systemd-core/nm-sd.h"
|
||||
|
||||
#if !defined(NM_DIST_VERSION)
|
||||
#define NM_DIST_VERSION VERSION
|
||||
#endif
|
||||
|
||||
#define NMIH_PID_FILE_FMT NMRUNDIR "/nm-iface-helper-%d.pid"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static struct {
|
||||
GMainLoop *main_loop;
|
||||
int ifindex;
|
||||
gboolean is_vrf_device;
|
||||
|
||||
guint dad_failed_id;
|
||||
CList dad_failed_lst_head;
|
||||
} gl /*obal*/ = {
|
||||
.ifindex = -1,
|
||||
.is_vrf_device = FALSE,
|
||||
};
|
||||
|
||||
static struct {
|
||||
gboolean slaac;
|
||||
gboolean show_version;
|
||||
gboolean become_daemon;
|
||||
gboolean debug;
|
||||
gboolean g_fatal_warnings;
|
||||
gboolean slaac_required;
|
||||
gboolean dhcp4_required;
|
||||
int tempaddr;
|
||||
char * ifname;
|
||||
char * uuid;
|
||||
char * stable_id;
|
||||
char * dhcp4_address;
|
||||
char * dhcp4_clientid;
|
||||
char * dhcp4_hostname;
|
||||
char * dhcp4_fqdn;
|
||||
char * mud_url;
|
||||
char * iid_str;
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
char * logging_backend;
|
||||
char * opt_log_level;
|
||||
char * opt_log_domains;
|
||||
guint32 priority_v4;
|
||||
guint32 priority_v6;
|
||||
} global_opt = {
|
||||
.tempaddr = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
|
||||
.priority_v4 = NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4,
|
||||
.priority_v6 = NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG_PREFIX_NAME "nm-iface-helper"
|
||||
#define _NMLOG(level, domain, ...) \
|
||||
nm_log((level), \
|
||||
(domain), \
|
||||
global_opt.ifname, \
|
||||
NULL, \
|
||||
"iface-helper: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) _NM_UTILS_MACRO_REST(__VA_ARGS__))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_dhcp_client_notify_cb(NMDhcpClient * client,
|
||||
const NMDhcpClientNotifyData *notify_data,
|
||||
gpointer user_data)
|
||||
{
|
||||
static NMIP4Config *last_config = NULL;
|
||||
NMIP4Config * existing;
|
||||
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
NMIP4Config * ip4_config;
|
||||
|
||||
if (!notify_data || notify_data->notify_type != NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED)
|
||||
g_return_if_reached();
|
||||
|
||||
nm_assert(!notify_data->state_changed.ip_config
|
||||
|| NM_IS_IP4_CONFIG(notify_data->state_changed.ip_config));
|
||||
|
||||
_LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", (int) notify_data->state_changed.dhcp_state);
|
||||
|
||||
switch (notify_data->state_changed.dhcp_state) {
|
||||
case NM_DHCP_STATE_BOUND:
|
||||
case NM_DHCP_STATE_EXTENDED:
|
||||
ip4_config = NM_IP4_CONFIG(notify_data->state_changed.ip_config);
|
||||
|
||||
g_assert(ip4_config);
|
||||
g_assert(nm_ip4_config_get_ifindex(ip4_config) == gl.ifindex);
|
||||
|
||||
existing = nm_ip4_config_capture(nm_platform_get_multi_idx(NM_PLATFORM_GET),
|
||||
NM_PLATFORM_GET,
|
||||
gl.ifindex);
|
||||
if (last_config)
|
||||
nm_ip4_config_subtract(existing, last_config, 0);
|
||||
|
||||
nm_ip4_config_merge(existing, ip4_config, NM_IP_CONFIG_MERGE_DEFAULT, 0);
|
||||
nm_ip4_config_add_dependent_routes(existing,
|
||||
RT_TABLE_MAIN,
|
||||
global_opt.priority_v4,
|
||||
gl.is_vrf_device,
|
||||
&ip4_dev_route_blacklist);
|
||||
if (!nm_ip4_config_commit(existing, NM_PLATFORM_GET, NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN))
|
||||
_LOGW(LOGD_DHCP4, "failed to apply DHCPv4 config");
|
||||
|
||||
if (!last_config && !nm_dhcp_client_accept(client, &error))
|
||||
_LOGW(LOGD_DHCP4, "failed to accept lease: %s", error->message);
|
||||
|
||||
nm_platform_ip4_dev_route_blacklist_set(NM_PLATFORM_GET,
|
||||
gl.ifindex,
|
||||
ip4_dev_route_blacklist);
|
||||
|
||||
if (last_config)
|
||||
g_object_unref(last_config);
|
||||
last_config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
|
||||
nm_dhcp_client_get_ifindex(client));
|
||||
nm_ip4_config_replace(last_config, ip4_config, NULL);
|
||||
break;
|
||||
case NM_DHCP_STATE_TIMEOUT:
|
||||
case NM_DHCP_STATE_DONE:
|
||||
case NM_DHCP_STATE_FAIL:
|
||||
if (global_opt.dhcp4_required) {
|
||||
_LOGW(LOGD_DHCP4, "DHCPv4 timed out or failed, quitting...");
|
||||
g_main_loop_quit(gl.main_loop);
|
||||
} else
|
||||
_LOGW(LOGD_DHCP4, "DHCPv4 timed out or failed");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ndisc_config_changed(NMNDisc * ndisc,
|
||||
const NMNDiscData *rdata,
|
||||
guint changed_int,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
static NMIP6Config *ndisc_config = NULL;
|
||||
NMIP6Config * existing;
|
||||
|
||||
existing = nm_ip6_config_capture(nm_platform_get_multi_idx(NM_PLATFORM_GET),
|
||||
NM_PLATFORM_GET,
|
||||
gl.ifindex,
|
||||
global_opt.tempaddr);
|
||||
if (ndisc_config)
|
||||
nm_ip6_config_subtract(existing, ndisc_config, 0);
|
||||
else {
|
||||
ndisc_config = nm_ip6_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), gl.ifindex);
|
||||
}
|
||||
|
||||
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(global_opt.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(ndisc_config,
|
||||
rdata->addresses,
|
||||
rdata->addresses_n,
|
||||
64,
|
||||
ifa_flags);
|
||||
}
|
||||
|
||||
if (NM_FLAGS_ANY(changed, NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_GATEWAYS)) {
|
||||
nm_ip6_config_reset_routes_ndisc(ndisc_config,
|
||||
rdata->gateways,
|
||||
rdata->gateways_n,
|
||||
rdata->routes,
|
||||
rdata->routes_n,
|
||||
RT_TABLE_MAIN,
|
||||
global_opt.priority_v6);
|
||||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
|
||||
/* Unsupported until systemd DHCPv6 is ready */
|
||||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_HOP_LIMIT)
|
||||
nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe(NM_PLATFORM_GET,
|
||||
global_opt.ifname,
|
||||
rdata->hop_limit);
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_REACHABLE_TIME) {
|
||||
nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(NM_PLATFORM_GET,
|
||||
global_opt.ifname,
|
||||
rdata->reachable_time_ms);
|
||||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_RETRANS_TIMER) {
|
||||
nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(NM_PLATFORM_GET,
|
||||
global_opt.ifname,
|
||||
rdata->retrans_timer_ms);
|
||||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_MTU) {
|
||||
nm_platform_sysctl_ip_conf_set_int64(NM_PLATFORM_GET,
|
||||
AF_INET6,
|
||||
global_opt.ifname,
|
||||
"mtu",
|
||||
rdata->mtu);
|
||||
}
|
||||
|
||||
nm_ip6_config_merge(existing, ndisc_config, NM_IP_CONFIG_MERGE_DEFAULT, 0);
|
||||
nm_ip6_config_add_dependent_routes(existing,
|
||||
RT_TABLE_MAIN,
|
||||
global_opt.priority_v6,
|
||||
gl.is_vrf_device);
|
||||
if (!nm_ip6_config_commit(existing, NM_PLATFORM_GET, NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, NULL))
|
||||
_LOGW(LOGD_IP6, "failed to apply IPv6 config");
|
||||
}
|
||||
|
||||
static void
|
||||
ndisc_ra_timeout(NMNDisc *ndisc, gpointer user_data)
|
||||
{
|
||||
if (global_opt.slaac_required) {
|
||||
_LOGW(LOGD_IP6, "IPv6 timed out or failed, quitting...");
|
||||
g_main_loop_quit(gl.main_loop);
|
||||
} else
|
||||
_LOGW(LOGD_IP6, "IPv6 timed out or failed");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
quit_handler(gpointer user_data)
|
||||
{
|
||||
g_main_loop_quit(gl.main_loop);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_signals(void)
|
||||
{
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
g_unix_signal_add(SIGINT, quit_handler, NULL);
|
||||
g_unix_signal_add(SIGTERM, quit_handler, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_early_setup(int *argc, char **argv[])
|
||||
{
|
||||
gint64 priority64_v4 = -1;
|
||||
gint64 priority64_v6 = -1;
|
||||
GOptionEntry options[] = {
|
||||
/* Interface/IP config */
|
||||
{"ifname",
|
||||
'i',
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.ifname,
|
||||
N_("The interface to manage"),
|
||||
"eth0"},
|
||||
{"uuid",
|
||||
'u',
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.uuid,
|
||||
N_("Connection UUID"),
|
||||
"661e8cd0-b618-46b8-9dc9-31a52baaa16b"},
|
||||
{"stable-id",
|
||||
'\0',
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.stable_id,
|
||||
N_("Connection Token for Stable IDs"),
|
||||
"eth"},
|
||||
{"slaac",
|
||||
's',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&global_opt.slaac,
|
||||
N_("Whether to manage IPv6 SLAAC"),
|
||||
NULL},
|
||||
{"slaac-required",
|
||||
'6',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&global_opt.slaac_required,
|
||||
N_("Whether SLAAC must be successful"),
|
||||
NULL},
|
||||
{"slaac-tempaddr",
|
||||
't',
|
||||
0,
|
||||
G_OPTION_ARG_INT,
|
||||
&global_opt.tempaddr,
|
||||
N_("Use an IPv6 temporary privacy address"),
|
||||
NULL},
|
||||
{"dhcp4",
|
||||
'd',
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.dhcp4_address,
|
||||
N_("Current DHCPv4 address"),
|
||||
NULL},
|
||||
{"dhcp4-required",
|
||||
'4',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&global_opt.dhcp4_required,
|
||||
N_("Whether DHCPv4 must be successful"),
|
||||
NULL},
|
||||
{"dhcp4-clientid",
|
||||
'c',
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.dhcp4_clientid,
|
||||
N_("Hex-encoded DHCPv4 client ID"),
|
||||
NULL},
|
||||
{"dhcp4-hostname",
|
||||
'h',
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.dhcp4_hostname,
|
||||
N_("Hostname to send to DHCP server"),
|
||||
N_("barbar")},
|
||||
{"dhcp4-fqdn",
|
||||
'F',
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.dhcp4_fqdn,
|
||||
N_("FQDN to send to DHCP server"),
|
||||
N_("host.domain.org")},
|
||||
{"priority4",
|
||||
'\0',
|
||||
0,
|
||||
G_OPTION_ARG_INT64,
|
||||
&priority64_v4,
|
||||
N_("Route priority for IPv4"),
|
||||
N_("0")},
|
||||
{"priority6",
|
||||
'\0',
|
||||
0,
|
||||
G_OPTION_ARG_INT64,
|
||||
&priority64_v6,
|
||||
N_("Route priority for IPv6"),
|
||||
N_("1024")},
|
||||
{"iid",
|
||||
'e',
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.iid_str,
|
||||
N_("Hex-encoded Interface Identifier"),
|
||||
""},
|
||||
{"addr-gen-mode",
|
||||
'e',
|
||||
0,
|
||||
G_OPTION_ARG_INT,
|
||||
&global_opt.addr_gen_mode,
|
||||
N_("IPv6 SLAAC address generation mode"),
|
||||
"eui64"},
|
||||
{"logging-backend",
|
||||
'\0',
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.logging_backend,
|
||||
N_("The logging backend configuration value. See logging.backend in NetworkManager.conf"),
|
||||
NULL},
|
||||
|
||||
/* Logging/debugging */
|
||||
{"version",
|
||||
'V',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&global_opt.show_version,
|
||||
N_("Print NetworkManager version and exit"),
|
||||
NULL},
|
||||
{"no-daemon",
|
||||
'n',
|
||||
G_OPTION_FLAG_REVERSE,
|
||||
G_OPTION_ARG_NONE,
|
||||
&global_opt.become_daemon,
|
||||
N_("Don't become a daemon"),
|
||||
NULL},
|
||||
{"debug",
|
||||
'b',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&global_opt.debug,
|
||||
N_("Don't become a daemon, and log to stderr"),
|
||||
NULL},
|
||||
{"log-level",
|
||||
0,
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.opt_log_level,
|
||||
N_("Log level: one of [%s]"),
|
||||
"INFO"},
|
||||
{"log-domains",
|
||||
0,
|
||||
0,
|
||||
G_OPTION_ARG_STRING,
|
||||
&global_opt.opt_log_domains,
|
||||
N_("Log domains separated by ',': any combination of [%s]"),
|
||||
"PLATFORM,RFKILL,WIFI"},
|
||||
{"g-fatal-warnings",
|
||||
0,
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&global_opt.g_fatal_warnings,
|
||||
N_("Make all warnings fatal"),
|
||||
NULL},
|
||||
{NULL}};
|
||||
|
||||
if (!nm_main_utils_early_setup("nm-iface-helper",
|
||||
argc,
|
||||
argv,
|
||||
options,
|
||||
NULL,
|
||||
NULL,
|
||||
_("nm-iface-helper is a small, standalone process that manages "
|
||||
"a single network interface.")))
|
||||
return FALSE;
|
||||
|
||||
if (priority64_v4 >= 0 && priority64_v4 <= G_MAXUINT32)
|
||||
global_opt.priority_v4 = (guint32) priority64_v4;
|
||||
if (priority64_v6 >= 0 && priority64_v6 <= G_MAXUINT32)
|
||||
global_opt.priority_v6 = (guint32) priority64_v6;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
NMPlatform *platform;
|
||||
NMNDisc * ndisc;
|
||||
} DadFailedHandleData;
|
||||
|
||||
static gboolean
|
||||
dad_failed_handle_idle(gpointer user_data)
|
||||
{
|
||||
DadFailedHandleData *data = user_data;
|
||||
NMCListElem * elem;
|
||||
|
||||
while ((elem = c_list_first_entry(&gl.dad_failed_lst_head, NMCListElem, lst))) {
|
||||
nm_auto_nmpobj const NMPObject *obj = elem->data;
|
||||
|
||||
nm_c_list_elem_free(elem);
|
||||
|
||||
if (nm_ndisc_dad_addr_is_fail_candidate(data->platform, obj)) {
|
||||
nm_ndisc_dad_failed(data->ndisc, &NMP_OBJECT_CAST_IP6_ADDRESS(obj)->address, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
gl.dad_failed_id = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
ip6_address_changed(NMPlatform * platform,
|
||||
int obj_type_i,
|
||||
int iface,
|
||||
const NMPlatformIP6Address *addr,
|
||||
int change_type_i,
|
||||
NMNDisc * ndisc)
|
||||
{
|
||||
const NMPlatformSignalChangeType change_type = change_type_i;
|
||||
DadFailedHandleData * data;
|
||||
|
||||
if (!nm_ndisc_dad_addr_is_fail_candidate_event(change_type, addr))
|
||||
return;
|
||||
|
||||
c_list_link_tail(
|
||||
&gl.dad_failed_lst_head,
|
||||
&nm_c_list_elem_new_stale((gpointer) nmp_object_ref(NMP_OBJECT_UP_CAST(addr)))->lst);
|
||||
if (gl.dad_failed_id)
|
||||
return;
|
||||
|
||||
data = g_slice_new(DadFailedHandleData);
|
||||
data->platform = platform;
|
||||
data->ndisc = ndisc;
|
||||
gl.dad_failed_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
|
||||
dad_failed_handle_idle,
|
||||
data,
|
||||
nm_g_slice_free_fcn(DadFailedHandleData));
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char * bad_domains = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean wrote_pidfile = FALSE;
|
||||
gs_free char * pidfile = NULL;
|
||||
gs_unref_object NMDhcpClient *dhcp4_client = NULL;
|
||||
gs_unref_object NMNDisc *ndisc = NULL;
|
||||
gs_unref_bytes GBytes *hwaddr = NULL;
|
||||
gs_unref_bytes GBytes *bcast_hwaddr = NULL;
|
||||
gs_unref_bytes GBytes *client_id = NULL;
|
||||
gs_free NMUtilsIPv6IfaceId *iid = NULL;
|
||||
const NMPlatformLink * pllink;
|
||||
guint sd_id;
|
||||
int errsv;
|
||||
|
||||
c_list_init(&gl.dad_failed_lst_head);
|
||||
|
||||
setpgid(getpid(), getpid());
|
||||
|
||||
if (!do_early_setup(&argc, &argv))
|
||||
return 1;
|
||||
|
||||
nm_logging_init_pre("nm-iface-helper",
|
||||
g_strdup_printf("%s[%ld] (%s): ",
|
||||
_NMLOG_PREFIX_NAME,
|
||||
(long) getpid(),
|
||||
global_opt.ifname ?: "???"));
|
||||
|
||||
if (global_opt.g_fatal_warnings) {
|
||||
GLogLevelFlags fatal_mask;
|
||||
|
||||
fatal_mask = g_log_set_always_fatal(G_LOG_FATAL_MASK);
|
||||
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
||||
g_log_set_always_fatal(fatal_mask);
|
||||
}
|
||||
|
||||
if (global_opt.show_version) {
|
||||
fprintf(stdout, NM_DIST_VERSION "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
nm_main_utils_ensure_root();
|
||||
|
||||
if (!global_opt.ifname || !global_opt.uuid) {
|
||||
fprintf(stderr, _("An interface name and UUID are required\n"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
gl.ifindex = nmp_utils_if_nametoindex(global_opt.ifname);
|
||||
if (gl.ifindex <= 0) {
|
||||
errsv = errno;
|
||||
fprintf(stderr,
|
||||
_("Failed to find interface index for %s (%s)\n"),
|
||||
global_opt.ifname,
|
||||
nm_strerror_native(errsv));
|
||||
return 1;
|
||||
}
|
||||
pidfile = g_strdup_printf(NMIH_PID_FILE_FMT, gl.ifindex);
|
||||
nm_main_utils_ensure_not_running_pidfile(pidfile);
|
||||
|
||||
nm_main_utils_ensure_rundir();
|
||||
|
||||
if (!nm_logging_setup(global_opt.opt_log_level,
|
||||
global_opt.opt_log_domains,
|
||||
&bad_domains,
|
||||
&error)) {
|
||||
fprintf(stderr,
|
||||
_("%s. Please use --help to see a list of valid options.\n"),
|
||||
error->message);
|
||||
return 1;
|
||||
} else if (bad_domains) {
|
||||
fprintf(stderr,
|
||||
_("Ignoring unrecognized log domain(s) '%s' passed on command line.\n"),
|
||||
bad_domains);
|
||||
nm_clear_g_free(&bad_domains);
|
||||
}
|
||||
|
||||
if (global_opt.become_daemon && !global_opt.debug) {
|
||||
if (daemon(0, 0) < 0) {
|
||||
errsv = errno;
|
||||
fprintf(stderr,
|
||||
_("Could not daemonize: %s [error %u]\n"),
|
||||
nm_strerror_native(errsv),
|
||||
errsv);
|
||||
return 1;
|
||||
}
|
||||
if (nm_main_utils_write_pidfile(pidfile))
|
||||
wrote_pidfile = TRUE;
|
||||
}
|
||||
|
||||
/* Set up unix signal handling - before creating threads, but after daemonizing! */
|
||||
gl.main_loop = g_main_loop_new(NULL, FALSE);
|
||||
setup_signals();
|
||||
|
||||
nm_logging_init(global_opt.logging_backend, global_opt.debug);
|
||||
|
||||
_LOGI(LOGD_CORE, "nm-iface-helper (version " NM_DIST_VERSION ") is starting...");
|
||||
|
||||
/* Set up platform interaction layer */
|
||||
nm_linux_platform_setup();
|
||||
|
||||
pllink = nm_platform_link_get(NM_PLATFORM_GET, gl.ifindex);
|
||||
if (pllink) {
|
||||
hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address);
|
||||
bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast);
|
||||
|
||||
if (pllink->master > 0) {
|
||||
gl.is_vrf_device =
|
||||
nm_platform_link_get_type(NM_PLATFORM_GET, pllink->master) == NM_LINK_TYPE_VRF;
|
||||
}
|
||||
}
|
||||
|
||||
if (global_opt.iid_str) {
|
||||
GBytes *bytes;
|
||||
gsize ignored = 0;
|
||||
|
||||
bytes = nm_utils_hexstr2bin(global_opt.iid_str);
|
||||
if (!bytes || g_bytes_get_size(bytes) != sizeof(*iid)) {
|
||||
fprintf(stderr, _("(%s): Invalid IID %s\n"), global_opt.ifname, global_opt.iid_str);
|
||||
return 1;
|
||||
}
|
||||
iid = g_bytes_unref_to_data(bytes, &ignored);
|
||||
}
|
||||
|
||||
if (global_opt.dhcp4_clientid) {
|
||||
/* this string is just a plain hex-string. Unlike ipv4.dhcp-client-id, which
|
||||
* is parsed via nm_dhcp_utils_client_id_string_to_bytes(). */
|
||||
client_id = nm_utils_hexstr2bin(global_opt.dhcp4_clientid);
|
||||
if (!client_id || g_bytes_get_size(client_id) < 2) {
|
||||
fprintf(stderr,
|
||||
_("(%s): Invalid DHCP client-id %s\n"),
|
||||
global_opt.ifname,
|
||||
global_opt.dhcp4_clientid);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (global_opt.dhcp4_address) {
|
||||
nm_platform_sysctl_ip_conf_set(NM_PLATFORM_GET,
|
||||
AF_INET,
|
||||
global_opt.ifname,
|
||||
"promote_secondaries",
|
||||
"1");
|
||||
|
||||
dhcp4_client = nm_dhcp_manager_start_ip4(nm_dhcp_manager_get(),
|
||||
nm_platform_get_multi_idx(NM_PLATFORM_GET),
|
||||
global_opt.ifname,
|
||||
gl.ifindex,
|
||||
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,
|
||||
global_opt.dhcp4_fqdn,
|
||||
NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP4,
|
||||
global_opt.mud_url,
|
||||
client_id,
|
||||
NM_DHCP_TIMEOUT_DEFAULT,
|
||||
NULL,
|
||||
global_opt.dhcp4_address,
|
||||
NULL,
|
||||
NULL,
|
||||
&error);
|
||||
if (!dhcp4_client)
|
||||
g_error("failure to start DHCP: %s", error->message);
|
||||
|
||||
g_signal_connect(dhcp4_client,
|
||||
NM_DHCP_CLIENT_NOTIFY,
|
||||
G_CALLBACK(_dhcp_client_notify_cb),
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (global_opt.slaac) {
|
||||
NMUtilsStableType stable_type = NM_UTILS_STABLE_TYPE_UUID;
|
||||
const char * stable_id = global_opt.uuid;
|
||||
int router_solicitation_interval;
|
||||
int router_solicitations;
|
||||
guint32 default_ra_timeout;
|
||||
int max_addresses;
|
||||
|
||||
nm_platform_link_set_inet6_addr_gen_mode(NM_PLATFORM_GET,
|
||||
gl.ifindex,
|
||||
NM_IN6_ADDR_GEN_MODE_NONE);
|
||||
|
||||
if (global_opt.stable_id
|
||||
&& (global_opt.stable_id[0] >= '0' && global_opt.stable_id[0] <= '9')
|
||||
&& global_opt.stable_id[1] == ' ') {
|
||||
/* strict parsing of --stable-id, which is the numeric stable-type
|
||||
* and the ID, joined with one space. For now, only support stable-types
|
||||
* from 0 to 9. */
|
||||
stable_type = (global_opt.stable_id[0] - '0');
|
||||
stable_id = &global_opt.stable_id[2];
|
||||
}
|
||||
|
||||
nm_ndisc_get_sysctl(NM_PLATFORM_GET,
|
||||
global_opt.ifname,
|
||||
&max_addresses,
|
||||
&router_solicitations,
|
||||
&router_solicitation_interval,
|
||||
&default_ra_timeout);
|
||||
|
||||
ndisc = nm_lndp_ndisc_new(NM_PLATFORM_GET,
|
||||
gl.ifindex,
|
||||
global_opt.ifname,
|
||||
stable_type,
|
||||
stable_id,
|
||||
global_opt.addr_gen_mode,
|
||||
NM_NDISC_NODE_TYPE_HOST,
|
||||
max_addresses,
|
||||
router_solicitations,
|
||||
router_solicitation_interval,
|
||||
default_ra_timeout,
|
||||
NULL);
|
||||
g_assert(ndisc);
|
||||
|
||||
if (iid)
|
||||
nm_ndisc_set_iid(ndisc, *iid);
|
||||
|
||||
nm_platform_sysctl_ip_conf_set(NM_PLATFORM_GET,
|
||||
AF_INET6,
|
||||
global_opt.ifname,
|
||||
"accept_ra",
|
||||
"0");
|
||||
|
||||
g_signal_connect(NM_PLATFORM_GET,
|
||||
NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
|
||||
G_CALLBACK(ip6_address_changed),
|
||||
ndisc);
|
||||
g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(ndisc_config_changed), NULL);
|
||||
g_signal_connect(ndisc, NM_NDISC_RA_TIMEOUT_SIGNAL, G_CALLBACK(ndisc_ra_timeout), NULL);
|
||||
nm_ndisc_start(ndisc);
|
||||
}
|
||||
|
||||
sd_id = nm_sd_event_attach_default();
|
||||
|
||||
g_main_loop_run(gl.main_loop);
|
||||
|
||||
nm_clear_g_source(&gl.dad_failed_id);
|
||||
nm_c_list_elem_free_all(&gl.dad_failed_lst_head, (GDestroyNotify) nmp_object_unref);
|
||||
|
||||
if (pidfile && wrote_pidfile)
|
||||
unlink(pidfile);
|
||||
|
||||
_LOGI(LOGD_CORE, "exiting");
|
||||
|
||||
nm_clear_g_source(&sd_id);
|
||||
nm_clear_pointer(&gl.main_loop, g_main_loop_unref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6] = {
|
||||
/* For nm-iface-helper there is no option to choose a DHCP plugin.
|
||||
* It just uses the "internal" one. */
|
||||
&_nm_dhcp_client_factory_internal,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Stub functions */
|
||||
|
||||
#include "nm-config.h"
|
||||
#include "devices/nm-device.h"
|
||||
#include "nm-active-connection.h"
|
||||
#include "nm-dbus-manager.h"
|
||||
|
||||
void
|
||||
nm_main_config_reload(int signal)
|
||||
{
|
||||
_LOGI(LOGD_CORE, "reloading configuration not supported");
|
||||
}
|
||||
|
||||
NMConfig *
|
||||
nm_config_get(void)
|
||||
{
|
||||
return GUINT_TO_POINTER(1);
|
||||
}
|
||||
|
||||
NMConfigData *
|
||||
nm_config_get_data_orig(NMConfig *config)
|
||||
{
|
||||
return GUINT_TO_POINTER(1);
|
||||
}
|
||||
|
||||
char *
|
||||
nm_config_data_get_value(const NMConfigData * config_data,
|
||||
const char * group,
|
||||
const char * key,
|
||||
NMConfigGetValueFlags flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NMConfigConfigureAndQuitType
|
||||
nm_config_get_configure_and_quit(NMConfig *config)
|
||||
{
|
||||
return NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED;
|
||||
}
|
||||
|
||||
NMDBusManager *
|
||||
nm_dbus_manager_get(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dbus_manager_is_stopping(NMDBusManager *self)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_nm_dbus_manager_obj_export(NMDBusObject *obj)
|
||||
{}
|
||||
|
||||
void
|
||||
_nm_dbus_manager_obj_unexport(NMDBusObject *obj)
|
||||
{}
|
||||
|
||||
void
|
||||
_nm_dbus_manager_obj_notify(NMDBusObject *obj, guint n_pspecs, const GParamSpec *const *pspecs)
|
||||
{}
|
||||
|
||||
void
|
||||
_nm_dbus_manager_obj_emit_signal(NMDBusObject * obj,
|
||||
const NMDBusInterfaceInfoExtended *interface_info,
|
||||
const GDBusSignalInfo * signal_info,
|
||||
GVariant * args)
|
||||
{}
|
||||
|
||||
GType
|
||||
nm_device_get_type(void)
|
||||
{
|
||||
g_return_val_if_reached(0);
|
||||
}
|
||||
|
||||
GType
|
||||
nm_active_connection_get_type(void)
|
||||
{
|
||||
g_return_val_if_reached(0);
|
||||
}
|
||||
|
|
@ -8,31 +8,125 @@
|
|||
|
||||
#include "nm-ip-config.h"
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "nm-l3cfg.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE(NMIPConfig, PROP_L3CFG, PROP_IS_VPN, );
|
||||
GType nm_ip4_config_get_type(void);
|
||||
GType nm_ip6_config_get_type(void);
|
||||
|
||||
typedef struct _NMIPConfigPrivate {
|
||||
NML3Cfg *l3cfg;
|
||||
bool is_vpn : 1;
|
||||
} NMIPConfigPrivate;
|
||||
/*****************************************************************************/
|
||||
|
||||
#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"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMIPConfigPrivate NMIPConfigPrivate;
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip,
|
||||
NMIPConfig,
|
||||
PROP_IP_L3CFG,
|
||||
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)
|
||||
{
|
||||
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,16 +138,14 @@ 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));
|
||||
break;
|
||||
case PROP_IS_VPN:
|
||||
/* construct-only */
|
||||
priv->is_vpn = g_value_get_boolean(value);
|
||||
ptr = g_value_get_pointer(value);
|
||||
nm_assert(NM_IS_L3CFG(ptr));
|
||||
priv->l3cfg = g_object_ref(ptr);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
|
|
@ -65,16 +157,10 @@ 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)
|
||||
nm_ip_config_new(int addr_family, NML3Cfg *l3cfg)
|
||||
{
|
||||
nm_assert_addr_family(addr_family);
|
||||
nm_assert(NM_L3CFG(l3cfg));
|
||||
|
|
@ -83,18 +169,50 @@ nm_ip_config_new(int addr_family, NML3Cfg *l3cfg, gboolean is_vpn)
|
|||
: nm_ip6_config_get_type(),
|
||||
NM_IP_CONFIG_L3CFG,
|
||||
l3cfg,
|
||||
NM_IP_CONFIG_IS_VPN,
|
||||
is_vpn,
|
||||
NULL);
|
||||
}
|
||||
|
||||
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 +220,610 @@ finalize(GObject *object)
|
|||
static void
|
||||
nm_ip_config_class_init(NMIPConfigClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
||||
GObjectClass * object_class = G_OBJECT_CLASS(klass);
|
||||
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
|
||||
|
||||
g_type_class_add_private(object_class, sizeof(NMIPConfigPrivate));
|
||||
|
||||
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] =
|
||||
g_param_spec_boolean(NM_IP_CONFIG_IS_VPN,
|
||||
obj_properties_ip[PROP_IP_ADDRESS_DATA] =
|
||||
g_param_spec_variant(NM_IP_CONFIG_ADDRESS_DATA,
|
||||
"",
|
||||
"",
|
||||
FALSE,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
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, obj_properties);
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define __NM_IP_CONFIG_H__
|
||||
|
||||
#include "nm-dbus-object.h"
|
||||
#include "nm-l3cfg.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -20,25 +21,65 @@
|
|||
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_IP_CONFIG, NMIPConfigClass))
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
struct _NMIPConfig {
|
||||
NMDBusObject parent;
|
||||
struct _NMIPConfigPrivate *_priv;
|
||||
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);
|
||||
NMIPConfig *nm_ip_config_new(int addr_family, NML3Cfg *l3cfg);
|
||||
|
||||
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__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,673 +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,
|
||||
NMSettingConnectionDnsOverTls dns_over_tls,
|
||||
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);
|
||||
NMSettingConnectionDnsOverTls nm_ip4_config_dns_over_tls_get(const NMIP4Config *self);
|
||||
void nm_ip4_config_dns_over_tls_set(NMIP4Config *self, NMSettingConnectionDnsOverTls dns_over_tls);
|
||||
|
||||
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__ */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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__ */
|
||||
|
|
@ -119,6 +119,7 @@ struct _NML3ConfigData {
|
|||
|
||||
NMSettingConnectionMdns mdns;
|
||||
NMSettingConnectionLlmnr llmnr;
|
||||
NMSettingConnectionDnsOverTls dns_over_tls;
|
||||
|
||||
NML3ConfigDatFlags flags;
|
||||
|
||||
|
|
@ -570,6 +571,16 @@ nm_l3_config_data_log(const NML3ConfigData *self,
|
|||
NULL)));
|
||||
}
|
||||
|
||||
if (self->dns_over_tls != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) {
|
||||
gs_free char *s = NULL;
|
||||
|
||||
_L("dns-over-tls: %s",
|
||||
(s = _nm_utils_enum_to_str_full(nm_setting_connection_dns_over_tls_get_type(),
|
||||
self->dns_over_tls,
|
||||
" ",
|
||||
NULL)));
|
||||
}
|
||||
|
||||
if (self->metered != NM_TERNARY_DEFAULT)
|
||||
_L("metered: %s", self->metered ? "yes" : "no");
|
||||
|
||||
|
|
@ -666,6 +677,7 @@ nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex, NMIPConfigSourc
|
|||
.multi_idx = nm_dedup_multi_index_ref(multi_idx),
|
||||
.mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT,
|
||||
.llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT,
|
||||
.dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT,
|
||||
.flags = NM_L3_CONFIG_DAT_FLAGS_NONE,
|
||||
.metered = NM_TERNARY_DEFAULT,
|
||||
.proxy_browser_only = NM_TERNARY_DEFAULT,
|
||||
|
|
@ -1679,6 +1691,26 @@ nm_l3_config_data_set_llmnr(NML3ConfigData *self, NMSettingConnectionLlmnr llmnr
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
NMSettingConnectionDnsOverTls
|
||||
nm_l3_config_data_get_dns_over_tls(const NML3ConfigData *self)
|
||||
{
|
||||
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
||||
|
||||
return self->dns_over_tls;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_l3_config_data_set_dns_over_tls(NML3ConfigData *self, NMSettingConnectionDnsOverTls dns_over_tls)
|
||||
{
|
||||
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
||||
|
||||
if (self->dns_over_tls == dns_over_tls)
|
||||
return FALSE;
|
||||
|
||||
self->dns_over_tls = dns_over_tls;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NMIPRouteTableSyncMode
|
||||
nm_l3_config_data_get_route_table_sync(const NML3ConfigData *self, int addr_family)
|
||||
{
|
||||
|
|
@ -2125,6 +2157,7 @@ nm_l3_config_data_cmp_full(const NML3ConfigData *a,
|
|||
NM_CMP_DIRECT_REF_STRING(a->nis_domain, b->nis_domain);
|
||||
NM_CMP_DIRECT(a->mdns, b->mdns);
|
||||
NM_CMP_DIRECT(a->llmnr, b->llmnr);
|
||||
NM_CMP_DIRECT(a->dns_over_tls, b->dns_over_tls);
|
||||
NM_CMP_DIRECT(a->mtu, b->mtu);
|
||||
NM_CMP_DIRECT(a->ip6_mtu, b->ip6_mtu);
|
||||
NM_CMP_DIRECT_UNSAFE(a->metered, b->metered);
|
||||
|
|
@ -3019,6 +3052,9 @@ nm_l3_config_data_merge(NML3ConfigData * self,
|
|||
if (self->llmnr == NM_SETTING_CONNECTION_LLMNR_DEFAULT)
|
||||
self->llmnr = src->llmnr;
|
||||
|
||||
if (self->dns_over_tls == NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT)
|
||||
self->dns_over_tls = src->dns_over_tls;
|
||||
|
||||
self->metered = NM_MAX((NMTernary) self->metered, (NMTernary) src->metered);
|
||||
|
||||
if (self->proxy_method == NM_PROXY_CONFIG_METHOD_UNKNOWN)
|
||||
|
|
|
|||
|
|
@ -446,6 +446,11 @@ NMSettingConnectionLlmnr nm_l3_config_data_get_llmnr(const NML3ConfigData *self)
|
|||
|
||||
gboolean nm_l3_config_data_set_llmnr(NML3ConfigData *self, NMSettingConnectionLlmnr llmnr);
|
||||
|
||||
NMSettingConnectionDnsOverTls nm_l3_config_data_get_dns_over_tls(const NML3ConfigData *self);
|
||||
|
||||
gboolean nm_l3_config_data_set_dns_over_tls(NML3ConfigData * self,
|
||||
NMSettingConnectionDnsOverTls dns_over_tls);
|
||||
|
||||
NMIPRouteTableSyncMode nm_l3_config_data_get_route_table_sync(const NML3ConfigData *self,
|
||||
int addr_family);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "nm-netns.h"
|
||||
#include "n-acd/src/n-acd.h"
|
||||
#include "nm-l3-ipv4ll.h"
|
||||
#include "nm-ip-config.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -246,6 +247,14 @@ typedef struct _NML3CfgPrivate {
|
|||
GSource *nacd_event_down_source;
|
||||
gint64 nacd_event_down_ratelimited_until_msec;
|
||||
|
||||
union {
|
||||
struct {
|
||||
NMIPConfig *ipconfig_6;
|
||||
NMIPConfig *ipconfig_4;
|
||||
};
|
||||
NMIPConfig *ipconfig_x[2];
|
||||
};
|
||||
|
||||
/* This is for rate-limiting the creation of nacd instance. */
|
||||
GSource *nacd_instance_ensure_retry;
|
||||
|
||||
|
|
@ -402,6 +411,73 @@ static NM_UTILS_LOOKUP_DEFINE(_l3_acd_addr_state_to_string,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMIPConfig *
|
||||
nm_l3cfg_ipconfig_get(NML3Cfg *self, int addr_family)
|
||||
{
|
||||
g_return_val_if_fail(NM_IS_L3CFG(self), NULL);
|
||||
nm_assert_addr_family(addr_family);
|
||||
|
||||
return self->priv.p->ipconfig_x[NM_IS_IPv4(addr_family)];
|
||||
}
|
||||
|
||||
static void
|
||||
_ipconfig_toggle_notify(gpointer data, GObject *object, gboolean is_last_ref)
|
||||
{
|
||||
NML3Cfg * self = NM_L3CFG(data);
|
||||
NMIPConfig *ipconfig = NM_IP_CONFIG(object);
|
||||
|
||||
if (!is_last_ref) {
|
||||
/* This happens while we take another ref below. Ignore the signal. */
|
||||
nm_assert(!NM_IN_SET(ipconfig, self->priv.p->ipconfig_4, self->priv.p->ipconfig_6));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ipconfig == self->priv.p->ipconfig_4)
|
||||
self->priv.p->ipconfig_4 = NULL;
|
||||
else {
|
||||
nm_assert(ipconfig == self->priv.p->ipconfig_6);
|
||||
self->priv.p->ipconfig_6 = NULL;
|
||||
}
|
||||
|
||||
/* We take a second reference to keep the instance alive, while also removing the
|
||||
* toggle ref. This will notify the function again, but we will ignore that. */
|
||||
g_object_ref(ipconfig);
|
||||
|
||||
g_object_remove_toggle_ref(G_OBJECT(ipconfig), _ipconfig_toggle_notify, self);
|
||||
|
||||
/* pass on the reference, and unexport on idle. */
|
||||
nm_ip_config_take_and_unexport_on_idle(g_steal_pointer(&ipconfig));
|
||||
}
|
||||
|
||||
NMIPConfig *
|
||||
nm_l3cfg_ipconfig_acquire(NML3Cfg *self, int addr_family)
|
||||
{
|
||||
NMIPConfig *ipconfig;
|
||||
|
||||
g_return_val_if_fail(NM_IS_L3CFG(self), NULL);
|
||||
nm_assert_addr_family(addr_family);
|
||||
|
||||
ipconfig = self->priv.p->ipconfig_x[NM_IS_IPv4(addr_family)];
|
||||
|
||||
if (ipconfig)
|
||||
return g_object_ref(ipconfig);
|
||||
|
||||
ipconfig = nm_ip_config_new(addr_family, self);
|
||||
|
||||
self->priv.p->ipconfig_x[NM_IS_IPv4(addr_family)] = ipconfig;
|
||||
|
||||
/* The ipconfig keeps self alive. We use a toggle reference
|
||||
* to avoid a cycle. But we anyway wouldn't want a strong reference,
|
||||
* because the user releases the instance by unrefing it, and we
|
||||
* notice that via the weak reference. */
|
||||
g_object_add_toggle_ref(G_OBJECT(ipconfig), _ipconfig_toggle_notify, self);
|
||||
|
||||
/* We keep the toggle reference, and return the other reference to the caller. */
|
||||
return g_steal_pointer(&ipconfig);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
nm_l3cfg_is_vrf(const NML3Cfg *self)
|
||||
{
|
||||
|
|
@ -4376,6 +4452,9 @@ finalize(GObject *object)
|
|||
{
|
||||
NML3Cfg *self = NM_L3CFG(object);
|
||||
|
||||
nm_assert(!self->priv.p->ipconfig_4);
|
||||
nm_assert(!self->priv.p->ipconfig_6);
|
||||
|
||||
nm_assert(!self->priv.p->l3_config_datas);
|
||||
nm_assert(!self->priv.p->ipv4ll);
|
||||
|
||||
|
|
|
|||
|
|
@ -447,4 +447,10 @@ void _nm_l3cfg_unregister_ipv4ll(NML3Cfg *self);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMIPConfig;
|
||||
struct _NMIPConfig *nm_l3cfg_ipconfig_get(NML3Cfg *self, int addr_family);
|
||||
struct _NMIPConfig *nm_l3cfg_ipconfig_acquire(NML3Cfg *self, int addr_family);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NM_L3CFG_H__ */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue