mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-24 16:00:07 +01:00
merge: branch 'next'
This is a refactor of IP configuration done by NM to make it more independent from NMDevice. See these files for more information: src/core/README.l3cfg.md src/core/README.next.ip-config.md https://bugzilla.redhat.com/show_bug.cgi?id=1868254
This commit is contained in:
commit
14962cb414
139 changed files with 12901 additions and 23424 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
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "libnm-platform/nm-platform.h"
|
||||
#include "libnm-platform/nm-linux-platform.h"
|
||||
#include "libnm-platform/nm-platform-utils.h"
|
||||
#include "nm-auth-utils.h"
|
||||
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
|
||||
|
||||
|
|
@ -227,6 +228,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 +1314,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 +1326,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 +1354,16 @@ nm_utils_ip_route_attribute_to_platform(int addr_family,
|
|||
|
||||
GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0);
|
||||
|
||||
if (!table && r->type_coerced == nm_platform_route_type_coerce(RTN_LOCAL))
|
||||
if (table != 0)
|
||||
r->table_coerced = nm_platform_route_table_coerce(table);
|
||||
else if (r->type_coerced == nm_platform_route_type_coerce(RTN_LOCAL))
|
||||
r->table_coerced = nm_platform_route_table_coerce(RT_TABLE_LOCAL);
|
||||
else if (route_table == 0)
|
||||
r->table_coerced = nm_platform_route_table_coerce(RT_TABLE_MAIN);
|
||||
else if (route_table > 0)
|
||||
r->table_coerced = nm_platform_route_table_coerce(route_table);
|
||||
else
|
||||
r->table_coerced = nm_platform_route_table_coerce(table ?: (route_table ?: RT_TABLE_MAIN));
|
||||
r->table_any = TRUE;
|
||||
|
||||
if (NM_IS_IPv4(addr_family)) {
|
||||
guint8 scope;
|
||||
|
|
@ -1395,39 +1419,20 @@ nm_utils_ip_route_attribute_to_platform(int addr_family,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
_addresses_sort_cmp_4(gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
return nm_platform_ip4_address_pretty_sort_cmp(
|
||||
NMP_OBJECT_CAST_IP4_ADDRESS(*((const NMPObject **) a)),
|
||||
NMP_OBJECT_CAST_IP4_ADDRESS(*((const NMPObject **) b)));
|
||||
}
|
||||
|
||||
static int
|
||||
_addresses_sort_cmp_6(gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
return nm_platform_ip6_address_pretty_sort_cmp(
|
||||
NMP_OBJECT_CAST_IP6_ADDRESS(*((const NMPObject **) a)),
|
||||
NMP_OBJECT_CAST_IP6_ADDRESS(*((const NMPObject **) b)),
|
||||
(((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT(user_data))
|
||||
== NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
|
||||
}
|
||||
|
||||
void
|
||||
nm_utils_ip_addresses_to_dbus(int addr_family,
|
||||
const NMDedupMultiHeadEntry *head_entry,
|
||||
const NMPObject * best_default_route,
|
||||
NMSettingIP6ConfigPrivacy ipv6_privacy,
|
||||
GVariant ** out_address_data,
|
||||
GVariant ** out_addresses)
|
||||
{
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
GVariantBuilder builder_data;
|
||||
GVariantBuilder builder_legacy;
|
||||
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
gs_free const NMPObject **addresses = NULL;
|
||||
guint naddr;
|
||||
guint i;
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
GVariantBuilder builder_data;
|
||||
GVariantBuilder builder_legacy;
|
||||
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
NMDedupMultiIter iter;
|
||||
const NMPObject *obj;
|
||||
guint i;
|
||||
|
||||
nm_assert_addr_family(addr_family);
|
||||
|
||||
|
|
@ -1443,19 +1448,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 +1524,8 @@ nm_utils_ip_addresses_to_dbus(int addr_family,
|
|||
: &in6addr_any));
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
@ -1654,6 +1653,134 @@ 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;
|
||||
}
|
||||
|
||||
if (route->rx.rt_source
|
||||
!= nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER)) {
|
||||
/* Ignore routes provided by external sources */
|
||||
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,15 +33,14 @@ 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;
|
||||
guint nas_update_count;
|
||||
int brfd;
|
||||
int nas_ifindex;
|
||||
char * nas_ifname;
|
||||
GSource *nas_update_source;
|
||||
guint nas_update_count;
|
||||
} NMDeviceAdslPrivate;
|
||||
|
||||
struct _NMDeviceAdsl {
|
||||
|
|
@ -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 && priv->nas_update_count <= 10) {
|
||||
/* Keep waiting for it to appear */
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
nm_clear_g_source_inst(&priv->nas_update_source);
|
||||
|
||||
if (priv->nas_ifindex <= 0) {
|
||||
if (priv->nas_update_count <= 10) {
|
||||
/* Keep waiting for it to appear */
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
priv->nas_update_id = 0;
|
||||
_LOGW(LOGD_ADSL,
|
||||
"failed to find br2684 interface %s ifindex after timeout",
|
||||
priv->nas_ifname);
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_BR2684_FAILED);
|
||||
return G_SOURCE_REMOVE;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
priv->nas_update_id = 0;
|
||||
_LOGD(LOGD_ADSL, "using br2684 iface '%s' index %d", priv->nas_ifname, priv->nas_ifindex);
|
||||
|
||||
if (!pppoe_vcc_config(self)) {
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_BR2684_FAILED);
|
||||
return G_SOURCE_REMOVE;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
nm_device_activate_schedule_stage2_device_config(device, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -319,11 +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) {
|
||||
|
|
@ -358,174 +358,187 @@ br2684_create_iface(NMDeviceAdsl *self)
|
|||
|
||||
nm_strdup_reset(&priv->nas_ifname, ni.ifname);
|
||||
_LOGD(LOGD_ADSL, "waiting for br2684 iface '%s' to appear", priv->nas_ifname);
|
||||
priv->nas_update_count = 0;
|
||||
priv->nas_update_id = g_timeout_add(100, nas_update_cb, self);
|
||||
priv->nas_update_count = 0;
|
||||
priv->nas_update_source = nm_g_timeout_add_source(100, nas_update_timeout_cb, self);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static 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);
|
||||
NMSettingAdsl * s_adsl;
|
||||
const char * protocol;
|
||||
|
||||
s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
|
||||
if (!priv->ppp_mgr) {
|
||||
gs_free_error GError *error = NULL;
|
||||
NMSettingAdsl * s_adsl;
|
||||
const char * protocol;
|
||||
NMActRequest * req;
|
||||
const char * ppp_iface;
|
||||
|
||||
g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
req = nm_device_get_act_request(device);
|
||||
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
protocol = nm_setting_adsl_get_protocol(s_adsl);
|
||||
_LOGD(LOGD_ADSL, "using ADSL protocol '%s'", protocol);
|
||||
s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL);
|
||||
g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) {
|
||||
/* PPPoA doesn't need anything special */
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
}
|
||||
protocol = nm_setting_adsl_get_protocol(s_adsl);
|
||||
|
||||
if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
|
||||
/* PPPoE needs RFC2684 bridging before we can do PPP over it */
|
||||
if (priv->nas_ifindex <= 0) {
|
||||
if (priv->nas_update_id == 0) {
|
||||
if (!br2684_create_iface(self)) {
|
||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED);
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
_LOGD(LOGD_ADSL, "using ADSL protocol '%s'", protocol);
|
||||
|
||||
if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) {
|
||||
/* PPPoA doesn't need anything special */
|
||||
} else if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
|
||||
/* PPPoE needs RFC2684 bridging before we can do PPP over it */
|
||||
if (priv->nas_ifindex <= 0) {
|
||||
if (!priv->nas_update_source) {
|
||||
if (!br2684_create_iface(self)) {
|
||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED);
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
}
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
} else
|
||||
nm_assert(nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM));
|
||||
|
||||
/* PPPoE uses the NAS interface, not the ATM interface */
|
||||
if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
|
||||
nm_assert(priv->nas_ifname);
|
||||
ppp_iface = priv->nas_ifname;
|
||||
_LOGD(LOGD_ADSL, "starting PPPoE on br2684 interface %s", priv->nas_ifname);
|
||||
} else {
|
||||
ppp_iface = nm_device_get_iface(device);
|
||||
_LOGD(LOGD_ADSL, "starting PPPoA");
|
||||
}
|
||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
_LOGW(LOGD_ADSL, "unhandled ADSL protocol '%s'", protocol);
|
||||
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
|
||||
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)
|
||||
act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
{
|
||||
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;
|
||||
NMPppMgrState ppp_state;
|
||||
|
||||
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);
|
||||
|
||||
/* PPPoE uses the NAS interface, not the ATM interface */
|
||||
if (nm_streq0(nm_setting_adsl_get_protocol(s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE)) {
|
||||
nm_assert(priv->nas_ifname);
|
||||
ppp_iface = priv->nas_ifname;
|
||||
|
||||
_LOGD(LOGD_ADSL, "starting PPPoE on br2684 interface %s", priv->nas_ifname);
|
||||
} else {
|
||||
ppp_iface = nm_device_get_iface(device);
|
||||
_LOGD(LOGD_ADSL, "starting PPPoA");
|
||||
if (!priv->ppp_mgr) {
|
||||
nm_assert_not_reached();
|
||||
return;
|
||||
}
|
||||
|
||||
priv->ppp_manager = nm_ppp_manager_create(ppp_iface, &err);
|
||||
ppp_state = nm_ppp_mgr_get_state(priv->ppp_mgr);
|
||||
|
||||
if (priv->ppp_manager) {
|
||||
nm_ppp_manager_set_route_parameters(priv->ppp_manager,
|
||||
nm_device_get_route_table(device, AF_INET),
|
||||
nm_device_get_route_metric(device, AF_INET),
|
||||
nm_device_get_route_table(device, AF_INET6),
|
||||
nm_device_get_route_metric(device, AF_INET6));
|
||||
nm_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;
|
||||
}
|
||||
|
||||
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);
|
||||
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 NMActStageReturn
|
||||
act_stage3_ip_config_start(NMDevice * device,
|
||||
int addr_family,
|
||||
gpointer * out_config,
|
||||
NMDeviceStateReason *out_failure_reason)
|
||||
{
|
||||
if (addr_family == AF_INET)
|
||||
return act_stage3_ip4_config_start(device, (NMIP4Config **) out_config, out_failure_reason);
|
||||
|
||||
return NM_DEVICE_CLASS(nm_device_adsl_parent_class)
|
||||
->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
|
||||
_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,
|
||||
|
|
@ -699,9 +704,9 @@ nm_device_adsl_class_init(NMDeviceAdslClass *klass)
|
|||
device_class->check_connection_compatible = check_connection_compatible;
|
||||
device_class->complete_connection = complete_connection;
|
||||
|
||||
device_class->act_stage2_config = act_stage2_config;
|
||||
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
|
||||
device_class->deactivate = deactivate;
|
||||
device_class->act_stage2_config = act_stage2_config;
|
||||
device_class->act_stage3_ip_config = act_stage3_ip_config;
|
||||
device_class->deactivate = deactivate;
|
||||
|
||||
obj_properties[PROP_ATM_INDEX] =
|
||||
g_param_spec_int(NM_DEVICE_ADSL_ATM_INDEX,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
NMDeviceBt *self = NM_DEVICE_BT(user_data);
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
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_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;
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device);
|
||||
|
||||
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,38 +14,36 @@
|
|||
#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_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */
|
||||
#define PPPOE_RECONNECT_DELAY_MSEC 7000
|
||||
#define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */
|
||||
|
||||
#define SUPPLICANT_LNK_TIMEOUT_SEC 15
|
||||
|
||||
|
|
@ -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,27 +471,26 @@ wired_auth_cond_fail(NMDeviceEthernet *self, NMDeviceStateReason reason)
|
|||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
|
||||
if (wired_auth_is_optional(self)) {
|
||||
_LOGI(
|
||||
LOGD_DEVICE | LOGD_ETHER,
|
||||
"Activation: (ethernet) 802.1X authentication is optional, continuing after a failure");
|
||||
if (NM_IN_SET(nm_device_get_state(device),
|
||||
NM_DEVICE_STATE_CONFIG,
|
||||
NM_DEVICE_STATE_NEED_AUTH))
|
||||
nm_device_activate_schedule_stage3_ip_config_start(device);
|
||||
|
||||
if (!priv->supplicant.auth_state_id) {
|
||||
priv->supplicant.auth_state_id =
|
||||
g_signal_connect(priv->supplicant.iface,
|
||||
"notify::" NM_SUPPLICANT_INTERFACE_AUTH_STATE,
|
||||
G_CALLBACK(supplicant_auth_state_changed),
|
||||
self);
|
||||
}
|
||||
if (!wired_auth_is_optional(self)) {
|
||||
supplicant_interface_release(self);
|
||||
nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
supplicant_interface_release(self);
|
||||
nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason);
|
||||
_LOGI(LOGD_DEVICE | LOGD_ETHER,
|
||||
"Activation: (ethernet) 802.1X authentication is optional, continuing after a failure");
|
||||
priv->supplicant.ready = TRUE;
|
||||
|
||||
if (NM_IN_SET(nm_device_get_state(device), NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_NEED_AUTH))
|
||||
nm_device_activate_schedule_stage2_device_config(device, FALSE);
|
||||
|
||||
if (!priv->supplicant.auth_state_id) {
|
||||
priv->supplicant.auth_state_id =
|
||||
g_signal_connect(priv->supplicant.iface,
|
||||
"notify::" NM_SUPPLICANT_INTERFACE_AUTH_STATE,
|
||||
G_CALLBACK(supplicant_auth_state_changed),
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -644,14 +646,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 +972,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 +1017,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 +1111,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 +1331,7 @@ dcb_state(NMDevice *device, gboolean timeout)
|
|||
nm_clear_g_source(&priv->dcb_timeout_id);
|
||||
priv->dcb_handle_carrier_changes = FALSE;
|
||||
priv->dcb_wait = DCB_WAIT_UNKNOWN;
|
||||
nm_device_activate_schedule_stage3_ip_config_start(device);
|
||||
nm_device_activate_schedule_stage2_device_config(device, FALSE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1407,31 +1387,98 @@ found:
|
|||
static NMActStageReturn
|
||||
act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
||||
{
|
||||
NMDeviceEthernet * self = (NMDeviceEthernet *) device;
|
||||
NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self);
|
||||
NMConnection * connection;
|
||||
NMSettingConnection * s_con;
|
||||
const char * connection_type;
|
||||
gboolean do_postpone = FALSE;
|
||||
NMSettingDcb * s_dcb;
|
||||
NMActRequest * req;
|
||||
|
||||
s_con = nm_device_get_applied_setting(device, NM_TYPE_SETTING_CONNECTION);
|
||||
connection = nm_device_get_applied_connection(device);
|
||||
g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
s_con = _nm_connection_get_setting(connection, NM_TYPE_SETTING_CONNECTION);
|
||||
g_return_val_if_fail(s_con, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
nm_clear_g_source(&priv->dcb_timeout_id);
|
||||
priv->dcb_handle_carrier_changes = FALSE;
|
||||
|
||||
connection_type = nm_setting_connection_get_connection_type(s_con);
|
||||
|
||||
if (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) {
|
||||
guint32 mtu;
|
||||
guint32 mru;
|
||||
guint32 mxu;
|
||||
|
||||
mtu = nm_setting_ppp_get_mtu(s_ppp);
|
||||
mru = nm_setting_ppp_get_mru(s_ppp);
|
||||
mxu = MAX(mru, mtu);
|
||||
if (mxu) {
|
||||
_LOGD(LOGD_PPP,
|
||||
"set MTU to %u (PPP interface MRU %u, MTU %u)",
|
||||
mxu + PPPOE_ENCAP_OVERHEAD,
|
||||
mru,
|
||||
mtu);
|
||||
nm_platform_link_set_mtu(nm_device_get_platform(device),
|
||||
nm_device_get_ifindex(device),
|
||||
mxu + PPPOE_ENCAP_OVERHEAD);
|
||||
}
|
||||
}
|
||||
|
||||
req = nm_device_get_act_request(device);
|
||||
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
s_pppoe = _nm_connection_get_setting(connection, NM_TYPE_SETTING_PPPOE);
|
||||
g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
priv->ppp_data.ppp_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;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
connection_type = nm_setting_connection_get_connection_type(s_con);
|
||||
if (nm_streq(connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
|
||||
NMSetting8021x *security;
|
||||
|
||||
security = nm_device_get_applied_setting(device, NM_TYPE_SETTING_802_1X);
|
||||
|
||||
if (security) {
|
||||
/* FIXME: for now 802.1x is mutually exclusive with DCB */
|
||||
/* FIXME: we always return from this. stage2 must be re-entrant, and
|
||||
* process all the necessary steps. Just returning for 8021x is wrong. */
|
||||
|
||||
if (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");
|
||||
|
|
@ -1450,7 +1497,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
|
||||
/* DCB and FCoE setup */
|
||||
s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_DCB);
|
||||
if (s_dcb) {
|
||||
if (!priv->stage2_ready_dcb && s_dcb) {
|
||||
/* lldpad really really wants the carrier to be up */
|
||||
if (nm_platform_link_is_connected(nm_device_get_platform(device),
|
||||
nm_device_get_ifindex(device))) {
|
||||
|
|
@ -1465,78 +1512,46 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
}
|
||||
|
||||
priv->dcb_handle_carrier_changes = TRUE;
|
||||
do_postpone = TRUE;
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
}
|
||||
|
||||
/* PPPoE setup */
|
||||
if (nm_connection_is_type(nm_device_get_applied_connection(device),
|
||||
NM_SETTING_PPPOE_SETTING_NAME)) {
|
||||
NMSettingPpp *s_ppp;
|
||||
|
||||
s_ppp = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPP);
|
||||
if (s_ppp) {
|
||||
guint32 mtu;
|
||||
guint32 mru;
|
||||
guint32 mxu;
|
||||
|
||||
mtu = nm_setting_ppp_get_mtu(s_ppp);
|
||||
mru = nm_setting_ppp_get_mru(s_ppp);
|
||||
mxu = MAX(mru, mtu);
|
||||
if (mxu) {
|
||||
_LOGD(LOGD_PPP,
|
||||
"set MTU to %u (PPP interface MRU %u, MTU %u)",
|
||||
mxu + PPPOE_ENCAP_OVERHEAD,
|
||||
mru,
|
||||
mtu);
|
||||
nm_platform_link_set_mtu(nm_device_get_platform(device),
|
||||
nm_device_get_ifindex(device),
|
||||
mxu + PPPOE_ENCAP_OVERHEAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return do_postpone ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ifindex = nm_device_get_ifindex(device);
|
||||
|
||||
if (ifindex <= 0)
|
||||
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_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 +1561,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 +1584,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 +1946,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 +2045,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,86 +39,92 @@ 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)
|
||||
{
|
||||
NMDevice * device = NM_DEVICE(user_data);
|
||||
NMDevicePpp * self = NM_DEVICE_PPP(device);
|
||||
gs_free char *old_name = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
if (!nm_device_take_over_link(device, ifindex, &old_name, &error)) {
|
||||
_LOGW(LOGD_DEVICE | LOGD_PPP,
|
||||
"could not take control of link %d: %s",
|
||||
ifindex,
|
||||
error->message);
|
||||
nm_device_state_changed(device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (old_name)
|
||||
nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP);
|
||||
|
||||
nm_device_activate_schedule_stage3_ip_config_start(device);
|
||||
}
|
||||
|
||||
static void
|
||||
_ppp_ip4_config_handle(NMDevicePpp *self)
|
||||
_ppp_mgr_stage3_maybe_ready(NMDevicePpp *self)
|
||||
{
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
|
||||
int IS_IPv4;
|
||||
|
||||
if (!priv->ip4_config)
|
||||
return;
|
||||
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
|
||||
const NMPppMgrIPData *ip_data;
|
||||
|
||||
if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG
|
||||
&& nm_device_activate_ip4_state_in_conf(device)) {
|
||||
nm_device_activate_schedule_ip_config_result(
|
||||
device,
|
||||
AF_INET,
|
||||
NM_IP_CONFIG_CAST(g_steal_pointer(&priv->ip4_config)));
|
||||
return;
|
||||
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_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
|
||||
_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data)
|
||||
{
|
||||
NMDevicePpp * self = NM_DEVICE_PPP(user_data);
|
||||
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
|
||||
NMDevicePpp * self = NM_DEVICE_PPP(user_data);
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMDeviceState device_state;
|
||||
|
||||
_LOGT(LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd");
|
||||
nm_g_object_ref_set(&priv->ip4_config, config);
|
||||
_ppp_ip4_config_handle(self);
|
||||
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_PPP);
|
||||
|
||||
nm_device_activate_schedule_stage2_device_config(device, FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_ppp_mgr_stage3_maybe_ready(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error)
|
||||
{
|
||||
|
|
@ -149,85 +152,80 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
|
||||
NMSettingPppoe * s_pppoe;
|
||||
NMActRequest * req;
|
||||
GError * error = NULL;
|
||||
|
||||
req = nm_device_get_act_request(device);
|
||||
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
if (!priv->ppp_mgr) {
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE);
|
||||
g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
req = nm_device_get_act_request(device);
|
||||
g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
g_clear_object(&priv->ip4_config);
|
||||
s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE);
|
||||
g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
priv->ppp_manager = nm_ppp_manager_create(nm_setting_pppoe_get_parent(s_pppoe), &error);
|
||||
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);
|
||||
*out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
|
||||
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)) {
|
||||
_LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message);
|
||||
g_error_free(error);
|
||||
|
||||
g_clear_object(&priv->ppp_manager);
|
||||
|
||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED);
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
|
||||
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"
|
||||
|
|
@ -85,11 +84,11 @@ parent_mtu_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_data
|
|||
static void
|
||||
parent_hwaddr_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
NMDevice * device = NM_DEVICE(user_data);
|
||||
NMDeviceVlan * self = NM_DEVICE_VLAN(device);
|
||||
NMConnection * connection;
|
||||
const char * new_mac, *old_mac;
|
||||
NMSettingIPConfig *s_ip6;
|
||||
NMDevice * device = NM_DEVICE(user_data);
|
||||
NMDeviceVlan *self = NM_DEVICE_VLAN(device);
|
||||
NMConnection *connection;
|
||||
const char * old_mac;
|
||||
const char * new_mac;
|
||||
|
||||
/* Never touch assumed devices */
|
||||
if (nm_device_sys_iface_state_is_external_or_assume(device))
|
||||
|
|
@ -113,13 +112,10 @@ parent_hwaddr_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_d
|
|||
NM_PRINT_FMT_QUOTE_STRING(new_mac));
|
||||
if (new_mac) {
|
||||
nm_device_hw_addr_set(device, new_mac, "vlan-parent", TRUE);
|
||||
nm_device_arp_announce(device);
|
||||
/* When changing the hw address the interface is taken down,
|
||||
* removing the IPv6 configuration; reapply it.
|
||||
*/
|
||||
s_ip6 = nm_connection_get_setting_ip6_config(connection);
|
||||
if (s_ip6)
|
||||
nm_device_reactivate_ip_config(device, AF_INET6, s_ip6, s_ip6);
|
||||
nm_device_l3cfg_commit(device, NM_L3_CFG_COMMIT_TYPE_UPDATE, 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,19 +1626,19 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static NMIPConfig *
|
||||
static const NML3ConfigData *
|
||||
_get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family)
|
||||
{
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
|
||||
gs_unref_object NMIPConfig *ip_config = NULL;
|
||||
NMConnection * connection;
|
||||
NMSettingWireGuard * s_wg;
|
||||
guint n_peers;
|
||||
guint i;
|
||||
int ip_ifindex;
|
||||
guint32 route_metric;
|
||||
guint32 route_table_coerced;
|
||||
gboolean auto_default_route_enabled;
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
NMConnection * connection;
|
||||
NMSettingWireGuard * s_wg;
|
||||
guint n_peers;
|
||||
guint i;
|
||||
int ip_ifindex;
|
||||
guint32 route_metric;
|
||||
guint32 route_table_coerced;
|
||||
gboolean auto_default_route_enabled;
|
||||
|
||||
_auto_default_route_init(self);
|
||||
|
||||
|
|
@ -1715,11 +1716,10 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!ip_config) {
|
||||
ip_config = nm_device_ip_config_new(NM_DEVICE(self), addr_family);
|
||||
nm_ip_config_set_config_flags(ip_config,
|
||||
NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES,
|
||||
0);
|
||||
if (!l3cd) {
|
||||
l3cd = nm_device_create_l3_config_data(NM_DEVICE(self), NM_IP_CONFIG_SOURCE_USER);
|
||||
nm_l3_config_data_set_flags(l3cd,
|
||||
NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES);
|
||||
}
|
||||
|
||||
nm_utils_ipx_address_clear_host_address(addr_family, &addrbin, NULL, prefix);
|
||||
|
|
@ -1754,27 +1754,23 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family)
|
|||
};
|
||||
}
|
||||
|
||||
nm_ip_config_add_route(ip_config, &rt.rx, NULL);
|
||||
nm_l3_config_data_add_route(l3cd, addr_family, NULL, &rt.rx);
|
||||
}
|
||||
}
|
||||
|
||||
return g_steal_pointer(&ip_config);
|
||||
if (!l3cd)
|
||||
return NULL;
|
||||
|
||||
return nm_l3_config_data_seal(g_steal_pointer(&l3cd));
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
act_stage3_ip_config_start(NMDevice * device,
|
||||
int addr_family,
|
||||
gpointer * out_config,
|
||||
NMDeviceStateReason *out_failure_reason)
|
||||
static void
|
||||
act_stage3_ip_config(NMDevice *device, int addr_family)
|
||||
{
|
||||
gs_unref_object NMIPConfig *ip_config = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
|
||||
ip_config = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family);
|
||||
|
||||
nm_device_set_dev2_ip_config(device, addr_family, ip_config);
|
||||
|
||||
return NM_DEVICE_CLASS(nm_device_wireguard_parent_class)
|
||||
->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
|
||||
l3cd = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family);
|
||||
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd);
|
||||
}
|
||||
|
||||
static guint32
|
||||
|
|
@ -1864,11 +1860,9 @@ can_reapply_change(NMDevice * device,
|
|||
static void
|
||||
reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_new)
|
||||
{
|
||||
NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device);
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
|
||||
gs_unref_object NMIPConfig *ip4_config = NULL;
|
||||
gs_unref_object NMIPConfig *ip6_config = NULL;
|
||||
NMDeviceState state = nm_device_get_state(device);
|
||||
NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device);
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
|
||||
NMDeviceState state = nm_device_get_state(device);
|
||||
|
||||
NM_DEVICE_CLASS(nm_device_wireguard_parent_class)->reapply_connection(device, con_old, con_new);
|
||||
|
||||
|
|
@ -1878,11 +1872,14 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne
|
|||
}
|
||||
|
||||
if (state >= NM_DEVICE_STATE_IP_CONFIG) {
|
||||
ip4_config = _get_dev2_ip_config(self, AF_INET);
|
||||
ip6_config = _get_dev2_ip_config(self, AF_INET6);
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd_4 = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd_6 = NULL;
|
||||
|
||||
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"
|
||||
|
|
@ -70,17 +71,17 @@
|
|||
#define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */
|
||||
|
||||
/* 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_IP6_PREFIX_DELEGATED "ip6-prefix-delegated"
|
||||
#define NM_DEVICE_IP6_SUBNET_NEEDED "ip6-subnet-needed"
|
||||
#define NM_DEVICE_REMOVED "removed"
|
||||
#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate"
|
||||
#define NM_DEVICE_RECHECK_ASSUME "recheck-assume"
|
||||
#define NM_DEVICE_STATE_CHANGED "state-changed"
|
||||
#define NM_DEVICE_LINK_INITIALIZED "link-initialized"
|
||||
#define NM_DEVICE_AUTOCONNECT_ALLOWED "autoconnect-allowed"
|
||||
#define NM_DEVICE_DNS_LOOKUP_DONE "dns-lookup-done"
|
||||
#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"
|
||||
#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate"
|
||||
#define NM_DEVICE_RECHECK_ASSUME "recheck-assume"
|
||||
#define NM_DEVICE_STATE_CHANGED "state-changed"
|
||||
#define NM_DEVICE_LINK_INITIALIZED "link-initialized"
|
||||
#define NM_DEVICE_AUTOCONNECT_ALLOWED "autoconnect-allowed"
|
||||
#define NM_DEVICE_PLATFORM_ADDRESS_CHANGED "platform-address-changed"
|
||||
|
||||
#define NM_DEVICE_STATISTICS_REFRESH_RATE_MS "refresh-rate-ms"
|
||||
#define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes"
|
||||
|
|
@ -344,15 +345,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 +456,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 +540,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 +747,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);
|
||||
NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(device);
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
gboolean indicate_addressing_running;
|
||||
NMConnection * connection;
|
||||
const char * method;
|
||||
|
|
@ -568,30 +566,30 @@ act_stage3_ip_config_start(NMDevice * device,
|
|||
method = nm_utils_get_ip_config_method(connection, addr_family);
|
||||
|
||||
/* We may have an address assigned by the group owner */
|
||||
if (NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) && priv->group_iface
|
||||
if (IS_IPv4 && NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) && priv->group_iface
|
||||
&& !nm_supplicant_interface_get_p2p_group_owner(priv->group_iface)) {
|
||||
in_addr_t addr;
|
||||
guint8 plen;
|
||||
|
||||
if (nm_supplicant_interface_get_p2p_assigned_addr(priv->group_iface, &addr, &plen)) {
|
||||
NMPlatformIP4Address address = {
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
NMPlatformIP4Address address = {
|
||||
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
};
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
|
||||
nm_platform_ip4_address_set_addr(&address, addr, plen);
|
||||
|
||||
ip4_config = nm_device_ip4_config_new(device);
|
||||
nm_ip4_config_add_address(ip4_config, &address);
|
||||
l3cd = nm_device_create_l3_config_data(device, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
nm_l3_config_data_add_address_4(l3cd, &address);
|
||||
|
||||
nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG(ip4_config));
|
||||
nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_READY, l3cd);
|
||||
|
||||
/* This just disables the addressing indicator. */
|
||||
method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr_family == AF_INET)
|
||||
if (IS_IPv4)
|
||||
indicate_addressing_running = NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
||||
else {
|
||||
indicate_addressing_running = NM_IN_STRSET(method,
|
||||
|
|
@ -603,9 +601,6 @@ act_stage3_ip_config_start(NMDevice * device,
|
|||
nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device),
|
||||
nm_device_get_ip_ifindex(device),
|
||||
TRUE);
|
||||
|
||||
return NM_DEVICE_CLASS(nm_device_wifi_p2p_parent_class)
|
||||
->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -757,7 +752,7 @@ check_group_iface_ready(NMDeviceWifiP2P *self)
|
|||
nm_clear_g_source(&priv->sup_timeout_id);
|
||||
update_disconnect_on_connection_peer_missing(self);
|
||||
|
||||
nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self));
|
||||
nm_device_activate_schedule_stage3_ip_config(NM_DEVICE(self), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1286,11 +1281,11 @@ nm_device_wifi_p2p_class_init(NMDeviceWifiP2PClass *klass)
|
|||
device_class->check_connection_compatible = check_connection_compatible;
|
||||
device_class->complete_connection = complete_connection;
|
||||
|
||||
device_class->act_stage1_prepare = act_stage1_prepare;
|
||||
device_class->act_stage2_config = act_stage2_config;
|
||||
device_class->get_configured_mtu = get_configured_mtu;
|
||||
device_class->get_auto_ip_config_method = get_auto_ip_config_method;
|
||||
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
|
||||
device_class->act_stage1_prepare = act_stage1_prepare;
|
||||
device_class->act_stage2_config = act_stage2_config;
|
||||
device_class->get_configured_mtu = get_configured_mtu;
|
||||
device_class->get_auto_ip_config_method = get_auto_ip_config_method;
|
||||
device_class->act_stage3_ip_config = act_stage3_ip_config;
|
||||
|
||||
device_class->deactivate = deactivate;
|
||||
device_class->unmanaged_on_quit = unmanaged_on_quit;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
const char * method;
|
||||
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;
|
||||
|
|
@ -3803,17 +3743,16 @@ nm_device_wifi_class_init(NMDeviceWifiClass *klass)
|
|||
device_class->get_guessed_metered = get_guessed_metered;
|
||||
device_class->set_enabled = set_enabled;
|
||||
|
||||
device_class->act_stage1_prepare = act_stage1_prepare;
|
||||
device_class->act_stage2_config = act_stage2_config;
|
||||
device_class->get_configured_mtu = get_configured_mtu;
|
||||
device_class->act_stage3_ip_config_start = act_stage3_ip_config_start;
|
||||
device_class->act_stage4_ip_config_timeout = act_stage4_ip_config_timeout;
|
||||
device_class->deactivate_async = deactivate_async;
|
||||
device_class->deactivate = deactivate;
|
||||
device_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr;
|
||||
device_class->unmanaged_on_quit = unmanaged_on_quit;
|
||||
device_class->can_reapply_change = can_reapply_change;
|
||||
device_class->reapply_connection = reapply_connection;
|
||||
device_class->act_stage1_prepare = act_stage1_prepare;
|
||||
device_class->act_stage2_config = act_stage2_config;
|
||||
device_class->get_configured_mtu = get_configured_mtu;
|
||||
device_class->act_stage3_ip_config = act_stage3_ip_config;
|
||||
device_class->deactivate_async = deactivate_async;
|
||||
device_class->deactivate = deactivate;
|
||||
device_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr;
|
||||
device_class->unmanaged_on_quit = unmanaged_on_quit;
|
||||
device_class->can_reapply_change = can_reapply_change;
|
||||
device_class->reapply_connection = reapply_connection;
|
||||
|
||||
device_class->state_changed = device_state_changed;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,11 +33,13 @@ typedef struct {
|
|||
NMModem * modem;
|
||||
NMDeviceModemCapabilities caps;
|
||||
NMDeviceModemCapabilities current_caps;
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
char * device_id;
|
||||
char * operator_code;
|
||||
char * apn;
|
||||
bool rf_enabled : 1;
|
||||
NMDeviceStageState stage1_state : 3;
|
||||
NMDeviceStageState stage2_state : 3;
|
||||
} NMDeviceModemPrivate;
|
||||
|
||||
struct _NMDeviceModem {
|
||||
|
|
@ -60,43 +62,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;
|
||||
}
|
||||
nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -188,102 +156,47 @@ 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)
|
||||
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)
|
||||
{
|
||||
NMDeviceModem *self = NM_DEVICE_MODEM(user_data);
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
g_return_if_fail(nm_device_devip_get_state(device, addr_family) == NM_DEVICE_IP_STATE_PENDING);
|
||||
|
||||
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);
|
||||
_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_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG_CAST(config));
|
||||
nm_device_activate_schedule_ip_config_result(device, AF_INET, NULL);
|
||||
}
|
||||
if (!IS_IPv4)
|
||||
priv->iid = iid ? *iid : ((NMUtilsIPv6IfaceId) NM_UTILS_IPV6_IFACE_ID_INIT);
|
||||
|
||||
static void
|
||||
modem_ip6_config_result(NMModem * modem,
|
||||
NMIP6Config *config,
|
||||
gboolean do_slaac,
|
||||
GError * error,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDeviceModem * self = NM_DEVICE_MODEM(user_data);
|
||||
NMDevice * device = NM_DEVICE(self);
|
||||
NMActStageReturn ret;
|
||||
NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
|
||||
gs_unref_object NMIP6Config *ignored = NULL;
|
||||
gboolean got_config = !!config;
|
||||
|
||||
if (!nm_device_activate_ip6_state_in_conf(device)) {
|
||||
_LOGD(LOGD_MB | LOGD_IP6,
|
||||
"retrieving IPv6 configuration while no longer in state IPv6 conf");
|
||||
return;
|
||||
if (do_auto) {
|
||||
if (IS_IPv4)
|
||||
nm_device_ip_method_dhcp4_start(device);
|
||||
else
|
||||
nm_device_ip_method_autoconf6_start(device);
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Re-enable IPv6 on the interface */
|
||||
nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "0");
|
||||
|
||||
if (config)
|
||||
nm_device_set_dev2_ip_config(device, AF_INET6, NM_IP_CONFIG_CAST(config));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
ip_ifindex_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE(user_data);
|
||||
NMDevice * device = NM_DEVICE(user_data);
|
||||
NMDeviceModem * self = NM_DEVICE_MODEM(device);
|
||||
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self);
|
||||
|
||||
if (!nm_device_is_activating(device))
|
||||
return;
|
||||
|
|
@ -300,6 +213,11 @@ ip_ifindex_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data)
|
|||
* RA handling code to run before NM is ready.
|
||||
*/
|
||||
nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "1");
|
||||
|
||||
if (priv->stage2_state == NM_DEVICE_STAGE_STATE_PENDING) {
|
||||
priv->stage2_state = NM_DEVICE_STAGE_STATE_COMPLETED;
|
||||
nm_device_activate_schedule_stage2_device_config(device, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -547,6 +465,7 @@ deactivate(NMDevice *device)
|
|||
|
||||
nm_modem_deactivate(priv->modem, device);
|
||||
priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT;
|
||||
priv->stage2_state = NM_DEVICE_STAGE_STATE_INIT;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -606,36 +525,28 @@ 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);
|
||||
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device);
|
||||
|
||||
if (priv->stage2_state == NM_DEVICE_STAGE_STATE_INIT) {
|
||||
priv->stage2_state = NM_DEVICE_STAGE_STATE_PENDING;
|
||||
return nm_modem_act_stage2_config(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem,
|
||||
device,
|
||||
out_failure_reason);
|
||||
}
|
||||
if (priv->stage2_state == NM_DEVICE_STAGE_STATE_PENDING)
|
||||
return NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
|
||||
nm_assert(priv->stage2_state == NM_DEVICE_STAGE_STATE_COMPLETED);
|
||||
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);
|
||||
}
|
||||
|
||||
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 +554,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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -703,6 +615,16 @@ is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ready_for_ip_config(NMDevice *device)
|
||||
{
|
||||
/* Tell NMDevice to only run device-specific IP
|
||||
* configuration (devip) and skip other methods
|
||||
* (manual, dhcp, etc).
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -716,8 +638,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 +825,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;
|
||||
|
|
@ -913,6 +833,7 @@ nm_device_modem_class_init(NMDeviceModemClass *klass)
|
|||
device_class->get_ip_iface_identifier = get_ip_iface_identifier;
|
||||
device_class->get_configured_mtu = nm_modem_get_configured_mtu;
|
||||
device_class->get_dhcp_timeout_for_device = get_dhcp_timeout_for_device;
|
||||
device_class->ready_for_ip_config = ready_for_ip_config;
|
||||
|
||||
device_class->state_changed = device_state_changed;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,249 +954,247 @@ 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 char * data_port;
|
||||
const char * address_string;
|
||||
const char * gw_string;
|
||||
guint32 address_network;
|
||||
guint32 gw = 0;
|
||||
NMPlatformIP4Address address;
|
||||
const char ** dns;
|
||||
guint i;
|
||||
guint32 ip4_route_table, ip4_route_metric;
|
||||
NMPlatformIP4Route * r;
|
||||
guint32 mtu_n;
|
||||
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 ** dns;
|
||||
guint i;
|
||||
gboolean do_auto = FALSE;
|
||||
int ifindex;
|
||||
NMUtilsIPv6IfaceId iid_data;
|
||||
const NMUtilsIPv6IfaceId *iid = NULL;
|
||||
|
||||
g_return_val_if_fail(self->_priv.ipv4_config, FALSE);
|
||||
g_return_val_if_fail(self->_priv.bearer, FALSE);
|
||||
if (IS_IPv4) {
|
||||
g_return_if_fail(self->_priv.ipv4_config);
|
||||
g_return_if_fail(self->_priv.bearer);
|
||||
|
||||
self->_priv.idle_id_ip4 = 0;
|
||||
if (ip_method == NM_MODEM_IP_METHOD_AUTO) {
|
||||
do_auto = TRUE;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
g_return_if_fail(self->_priv.ipv6_config);
|
||||
}
|
||||
|
||||
_LOGI("IPv4 static configuration:");
|
||||
if (IS_IPv4) {
|
||||
guint32 address_network;
|
||||
guint32 gw = 0;
|
||||
NMPlatformIP4Address address;
|
||||
NMPlatformIP4Route route;
|
||||
guint32 mtu_n;
|
||||
const char * gw_string;
|
||||
|
||||
/* Fully fail if invalid IP address retrieved */
|
||||
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,
|
||||
_LOGI("IPv4 static configuration:");
|
||||
|
||||
/* Fully fail if invalid IP address retrieved */
|
||||
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)) {
|
||||
g_set_error(&error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||
"(%s) retrieving IP4 configuration failed: invalid address given %s%s%s",
|
||||
nm_modem_get_uid(NM_MODEM(self)),
|
||||
NM_PRINT_FMT_QUOTE_STRING(address_string));
|
||||
goto out;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Missing gateway not a hard failure */
|
||||
gw_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv4_config);
|
||||
if (gw_string && !nm_utils_parse_inaddr_bin(AF_INET, gw_string, NULL, &gw)) {
|
||||
error =
|
||||
g_error_new(NM_DEVICE_ERROR,
|
||||
/* 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)) {
|
||||
g_set_error(&error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||
"(%s) retrieving IP4 configuration failed: invalid gateway address \"%s\"",
|
||||
nm_modem_get_uid(NM_MODEM(self)),
|
||||
gw_string);
|
||||
goto out;
|
||||
}
|
||||
|
||||
data_port = mm_bearer_get_interface(self->_priv.bearer);
|
||||
g_return_val_if_fail(data_port, FALSE);
|
||||
config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
|
||||
nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port));
|
||||
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.address = address_network;
|
||||
address.peer_address = address_network;
|
||||
address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv4_config);
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_WWAN;
|
||||
if (address.plen <= 32)
|
||||
nm_ip4_config_add_address(config, &address);
|
||||
|
||||
_LOGI(" address %s/%d", address_string, address.plen);
|
||||
|
||||
nm_modem_get_route_parameters(NM_MODEM(self), &ip4_route_table, &ip4_route_metric, NULL, NULL);
|
||||
r = &(NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
|
||||
.gateway = gw,
|
||||
.table_coerced = nm_platform_route_table_coerce(ip4_route_table),
|
||||
.metric = ip4_route_metric,
|
||||
};
|
||||
nm_ip4_config_add_route(config, r, NULL);
|
||||
_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);
|
||||
_LOGI(" DNS %s", dns[i]);
|
||||
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;
|
||||
}
|
||||
|
||||
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_l3_config_data_add_address_4(l3cd, &address);
|
||||
|
||||
_LOGI(" address %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf)));
|
||||
|
||||
route = (NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
|
||||
.gateway = gw,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = 0,
|
||||
};
|
||||
nm_l3_config_data_add_route_4(l3cd, &route);
|
||||
_LOGI(" gateway %s", gw_string);
|
||||
|
||||
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_l3_config_data_add_nameserver(l3cd, AF_INET, &address_network);
|
||||
_LOGI(" DNS %s", dns[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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);
|
||||
_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;
|
||||
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,
|
||||
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||
"(%s) retrieving IPv6 configuration failed: no address given",
|
||||
nm_modem_get_uid(NM_MODEM(self)));
|
||||
mtu_n = mm_bearer_ip_config_get_mtu(self->_priv.ipv4_config);
|
||||
if (mtu_n) {
|
||||
nm_l3_config_data_set_mtu(l3cd, mtu_n);
|
||||
_LOGI(" MTU %u", mtu_n);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
NMPlatformIP6Address address;
|
||||
|
||||
/* Fail if invalid IP address retrieved */
|
||||
if (!inet_pton(AF_INET6, address_string, (void *) &(address.address))) {
|
||||
error = g_error_new(NM_DEVICE_ERROR,
|
||||
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) {
|
||||
g_set_error(&error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||
"(%s) retrieving IPv6 configuration failed: invalid address given '%s'",
|
||||
nm_modem_get_uid(NM_MODEM(self)),
|
||||
address_string);
|
||||
goto out;
|
||||
}
|
||||
"(%s) retrieving IPv6 configuration failed: no address given",
|
||||
nm_modem_get_uid(NM_MODEM(self)));
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
_LOGI("IPv6 base configuration:");
|
||||
address = (NMPlatformIP6Address){};
|
||||
|
||||
data_port = mm_bearer_get_interface(self->_priv.bearer);
|
||||
g_return_val_if_fail(data_port, FALSE);
|
||||
if (!inet_pton(AF_INET6, address_string, &address.address)) {
|
||||
g_set_error(&error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||
"(%s) retrieving IPv6 configuration failed: invalid address given '%s'",
|
||||
nm_modem_get_uid(NM_MODEM(self)),
|
||||
address_string);
|
||||
goto out;
|
||||
}
|
||||
|
||||
config = nm_ip6_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
|
||||
nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port));
|
||||
data_port = mm_bearer_get_interface(self->_priv.bearer);
|
||||
g_return_if_fail(data_port);
|
||||
|
||||
address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv6_config);
|
||||
if (address.plen <= 128)
|
||||
nm_ip6_config_add_address(config, &address);
|
||||
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(" address %s/%d", address_string, address.plen);
|
||||
_LOGI("IPv6 base configuration:");
|
||||
|
||||
address_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv6_config);
|
||||
if (address_string) {
|
||||
guint32 ip6_route_table, ip6_route_metric;
|
||||
l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
|
||||
ifindex,
|
||||
NM_IP_CONFIG_SOURCE_WWAN);
|
||||
|
||||
if (inet_pton(AF_INET6, address_string, &address.address) != 1) {
|
||||
error =
|
||||
g_error_new(NM_DEVICE_ERROR,
|
||||
do_auto = TRUE;
|
||||
|
||||
address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv6_config);
|
||||
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 (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) {
|
||||
if (inet_pton(AF_INET6, address_string, &address.address) != 1) {
|
||||
g_set_error(&error,
|
||||
NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||
"(%s) retrieving IPv6 configuration failed: invalid gateway given '%s'",
|
||||
nm_modem_get_uid(NM_MODEM(self)),
|
||||
address_string);
|
||||
goto out;
|
||||
}
|
||||
|
||||
{
|
||||
const NMPlatformIP6Route r = {
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
|
||||
.gateway = address.address,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = 0,
|
||||
};
|
||||
|
||||
_LOGI(" gateway %s", address_string);
|
||||
nm_l3_config_data_add_route_6(l3cd, &r);
|
||||
}
|
||||
} else if (ip_method == NM_MODEM_IP_METHOD_STATIC) {
|
||||
/* Gateway required for the 'static' method */
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
dns = mm_bearer_ip_config_get_dns(self->_priv.ipv6_config);
|
||||
for (i = 0; dns && dns[i]; i++) {
|
||||
struct in6_addr addr;
|
||||
|
||||
_LOGI(" gateway %s", address_string);
|
||||
nm_ip6_config_add_route(config, &r, NULL);
|
||||
}
|
||||
} else if (ip_method == NM_MODEM_IP_METHOD_STATIC) {
|
||||
/* Gateway required for the 'static' method */
|
||||
error = g_error_new(NM_DEVICE_ERROR,
|
||||
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||
"(%s) retrieving IPv6 configuration failed: missing gateway",
|
||||
nm_modem_get_uid(NM_MODEM(self)));
|
||||
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);
|
||||
_LOGI(" DNS %s", dns[i]);
|
||||
if (inet_pton(AF_INET6, dns[i], &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_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = 0,
|
||||
};
|
||||
|
||||
{
|
||||
const NMPlatformIP4Route mms_route = {
|
||||
.network = address_network,
|
||||
.plen = 32,
|
||||
.gateway = gateway_network,
|
||||
.table_coerced = nm_platform_route_table_coerce(ip4_route_table),
|
||||
.metric = ip4_route_metric,
|
||||
};
|
||||
|
||||
nm_ip4_config_add_route(priv->ip4_config, &mms_route, NULL);
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
NMModemOfono * self = NM_MODEM_OFONO(modem);
|
||||
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
|
||||
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);
|
||||
|
|
@ -1300,6 +1306,6 @@ nm_modem_ofono_class_init(NMModemOfonoClass *klass)
|
|||
modem_class->deactivate_cleanup = deactivate_cleanup;
|
||||
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->modem_act_stage1_prepare = modem_act_stage1_prepare;
|
||||
modem_class->stage3_ip_config_start = stage3_ip_config_start;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -32,15 +32,14 @@
|
|||
#define NM_MODEM_APN "apn"
|
||||
|
||||
/* Signals */
|
||||
#define NM_MODEM_PPP_STATS "ppp-stats"
|
||||
#define NM_MODEM_PPP_FAILED "ppp-failed"
|
||||
#define NM_MODEM_PREPARE_RESULT "prepare-result"
|
||||
#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result"
|
||||
#define NM_MODEM_IP6_CONFIG_RESULT "ip6-config-result"
|
||||
#define NM_MODEM_AUTH_REQUESTED "auth-requested"
|
||||
#define NM_MODEM_AUTH_RESULT "auth-result"
|
||||
#define NM_MODEM_REMOVED "removed"
|
||||
#define NM_MODEM_STATE_CHANGED "state-changed"
|
||||
#define NM_MODEM_PPP_STATS "ppp-stats"
|
||||
#define NM_MODEM_PPP_FAILED "ppp-failed"
|
||||
#define NM_MODEM_PREPARE_RESULT "prepare-result"
|
||||
#define NM_MODEM_NEW_CONFIG "new-config"
|
||||
#define NM_MODEM_AUTH_REQUESTED "auth-requested"
|
||||
#define NM_MODEM_AUTH_RESULT "auth-result"
|
||||
#define NM_MODEM_REMOVED "removed"
|
||||
#define NM_MODEM_STATE_CHANGED "state-changed"
|
||||
|
||||
typedef enum {
|
||||
NM_MODEM_IP_METHOD_UNKNOWN = 0,
|
||||
|
|
@ -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_act_stage2_config(NMModem * self,
|
||||
NMDevice * device,
|
||||
NMDeviceStateReason *out_failure_reason);
|
||||
|
||||
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,
|
||||
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,26 +333,28 @@ dhclient_start(NMDhcpClient *client,
|
|||
const char * mode_opt,
|
||||
gboolean release,
|
||||
pid_t * out_pid,
|
||||
int prefixes,
|
||||
GError ** error)
|
||||
{
|
||||
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
|
||||
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
|
||||
gs_unref_ptrarray GPtrArray *argv = NULL;
|
||||
pid_t pid;
|
||||
gs_free_error GError *local = NULL;
|
||||
const char * iface;
|
||||
const char * uuid;
|
||||
const char * system_bus_address;
|
||||
const char * dhclient_path;
|
||||
char * binary_name;
|
||||
gs_free char * cmd_str = NULL;
|
||||
gs_free char * pid_file = NULL;
|
||||
gs_free char * system_bus_address_env = NULL;
|
||||
gs_free char * preferred_leasefile_path = NULL;
|
||||
const int addr_family = nm_dhcp_client_get_addr_family(client);
|
||||
gs_free_error GError * local = NULL;
|
||||
const char * iface;
|
||||
const char * uuid;
|
||||
const char * system_bus_address;
|
||||
const char * dhclient_path;
|
||||
char * binary_name;
|
||||
gs_free char * cmd_str = NULL;
|
||||
gs_free char * pid_file = NULL;
|
||||
gs_free char * system_bus_address_env = NULL;
|
||||
gs_free char * preferred_leasefile_path = NULL;
|
||||
int addr_family;
|
||||
const NMDhcpClientConfig *client_config;
|
||||
|
||||
g_return_val_if_fail(!priv->pid_file, FALSE);
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
addr_family = client_config->addr_family;
|
||||
|
||||
NM_SET_OUT(out_pid, 0);
|
||||
|
||||
|
|
@ -362,8 +364,8 @@ dhclient_start(NMDhcpClient *client,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
iface = nm_dhcp_client_get_iface(client);
|
||||
uuid = nm_dhcp_client_get_uuid(client);
|
||||
iface = client_config->iface;
|
||||
uuid = client_config->uuid;
|
||||
|
||||
pid_file = g_strdup_printf(NMRUNDIR "/dhclient%s-%s.pid",
|
||||
_addr_family_to_path_part(addr_family),
|
||||
|
|
@ -409,9 +411,7 @@ dhclient_start(NMDhcpClient *client,
|
|||
|
||||
/* Save the DUID to the leasefile dhclient will actually use */
|
||||
if (addr_family == AF_INET6) {
|
||||
if (!nm_dhcp_dhclient_save_duid(priv->lease_file,
|
||||
nm_dhcp_client_get_client_id(client),
|
||||
&local)) {
|
||||
if (!nm_dhcp_dhclient_save_duid(priv->lease_file, client_config->client_id, &local)) {
|
||||
nm_utils_error_set(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"failed to save DUID to '%s': %s",
|
||||
|
|
@ -434,13 +434,13 @@ dhclient_start(NMDhcpClient *client,
|
|||
if (release)
|
||||
g_ptr_array_add(argv, (gpointer) "-r");
|
||||
|
||||
if (!release
|
||||
&& NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
|
||||
NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST)) {
|
||||
if (!release && client_config->addr_family == AF_INET && client_config->v4.request_broadcast) {
|
||||
g_ptr_array_add(argv, (gpointer) "-B");
|
||||
}
|
||||
|
||||
if (addr_family == AF_INET6) {
|
||||
guint prefixes = client_config->v6.needed_prefixes;
|
||||
|
||||
g_ptr_array_add(argv, (gpointer) "-6");
|
||||
|
||||
if (prefixes > 0 && nm_streq0(mode_opt, "-S")) {
|
||||
|
|
@ -513,29 +513,28 @@ dhclient_start(NMDhcpClient *client,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
||||
ip4_start(NMDhcpClient *client, GError **error)
|
||||
{
|
||||
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
|
||||
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
|
||||
GBytes * client_id;
|
||||
gs_unref_bytes GBytes *new_client_id = NULL;
|
||||
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
|
||||
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
|
||||
gs_unref_bytes GBytes * new_client_id = NULL;
|
||||
const NMDhcpClientConfig *client_config;
|
||||
|
||||
client_id = nm_dhcp_client_get_client_id(client);
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
|
||||
priv->conf_file = create_dhclient_config(
|
||||
self,
|
||||
AF_INET,
|
||||
nm_dhcp_client_get_iface(client),
|
||||
nm_dhcp_client_get_uuid(client),
|
||||
client_id,
|
||||
nm_dhcp_client_get_anycast_address(client),
|
||||
nm_dhcp_client_get_hostname(client),
|
||||
nm_dhcp_client_get_timeout(client),
|
||||
NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN),
|
||||
nm_dhcp_client_get_hostname_flags(client),
|
||||
nm_dhcp_client_get_mud_url(client),
|
||||
nm_dhcp_client_get_reject_servers(client),
|
||||
&new_client_id);
|
||||
priv->conf_file = create_dhclient_config(self,
|
||||
AF_INET,
|
||||
client_config->iface,
|
||||
client_config->uuid,
|
||||
client_config->client_id,
|
||||
client_config->anycast_address,
|
||||
client_config->hostname,
|
||||
client_config->timeout,
|
||||
client_config->use_fqdn,
|
||||
client_config->hostname_flags,
|
||||
client_config->mud_url,
|
||||
client_config->reject_servers,
|
||||
&new_client_id);
|
||||
if (!priv->conf_file) {
|
||||
nm_utils_error_set_literal(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
|
|
@ -544,36 +543,35 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
|||
}
|
||||
|
||||
if (new_client_id) {
|
||||
nm_assert(!client_id);
|
||||
nm_dhcp_client_set_client_id(client, new_client_id);
|
||||
nm_assert(!client_config->client_id);
|
||||
nm_dhcp_client_set_effective_client_id(client, new_client_id);
|
||||
}
|
||||
return dhclient_start(client, NULL, FALSE, NULL, 0, error);
|
||||
return dhclient_start(client, NULL, FALSE, NULL, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip6_start(NMDhcpClient * client,
|
||||
const struct in6_addr * ll_addr,
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
guint needed_prefixes,
|
||||
GError ** error)
|
||||
ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error)
|
||||
{
|
||||
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
|
||||
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
|
||||
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
|
||||
NMDhcpDhclientPrivate * priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
|
||||
const NMDhcpClientConfig *config;
|
||||
|
||||
if (nm_dhcp_client_get_iaid_explicit(client))
|
||||
config = nm_dhcp_client_get_config(client);
|
||||
|
||||
if (config->v6.iaid_explicit)
|
||||
_LOGW("dhclient does not support specifying an IAID for DHCPv6, it will be ignored");
|
||||
|
||||
priv->conf_file = create_dhclient_config(self,
|
||||
AF_INET6,
|
||||
nm_dhcp_client_get_iface(client),
|
||||
nm_dhcp_client_get_uuid(client),
|
||||
config->iface,
|
||||
config->uuid,
|
||||
NULL,
|
||||
nm_dhcp_client_get_anycast_address(client),
|
||||
nm_dhcp_client_get_hostname(client),
|
||||
nm_dhcp_client_get_timeout(client),
|
||||
config->anycast_address,
|
||||
config->hostname,
|
||||
config->timeout,
|
||||
TRUE,
|
||||
nm_dhcp_client_get_hostname_flags(client),
|
||||
nm_dhcp_client_get_mud_url(client),
|
||||
config->hostname_flags,
|
||||
config->mud_url,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!priv->conf_file) {
|
||||
|
|
@ -583,15 +581,7 @@ ip6_start(NMDhcpClient * client,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
return dhclient_start(client,
|
||||
NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
|
||||
NM_DHCP_CLIENT_FLAGS_INFO_ONLY)
|
||||
? "-S"
|
||||
: "-N",
|
||||
FALSE,
|
||||
NULL,
|
||||
needed_prefixes,
|
||||
error);
|
||||
return dhclient_start(client, config->v6.needed_prefixes ? "-S" : "-N", FALSE, NULL, error);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -625,7 +615,7 @@ stop(NMDhcpClient *client, gboolean release)
|
|||
if (release) {
|
||||
pid_t rpid = -1;
|
||||
|
||||
if (dhclient_start(client, NULL, TRUE, &rpid, 0, NULL)) {
|
||||
if (dhclient_start(client, NULL, TRUE, &rpid, NULL)) {
|
||||
/* Wait a few seconds for the release to happen */
|
||||
nm_dhcp_client_stop_pid(rpid, nm_dhcp_client_get_iface(client));
|
||||
}
|
||||
|
|
@ -635,16 +625,19 @@ stop(NMDhcpClient *client, gboolean release)
|
|||
static GBytes *
|
||||
get_duid(NMDhcpClient *client)
|
||||
{
|
||||
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
|
||||
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
|
||||
GBytes * duid = NULL;
|
||||
gs_free char * leasefile = NULL;
|
||||
GError * error = NULL;
|
||||
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
|
||||
NMDhcpDhclientPrivate * priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
|
||||
const NMDhcpClientConfig *client_config;
|
||||
GBytes * duid = NULL;
|
||||
gs_free char * leasefile = NULL;
|
||||
GError * error = NULL;
|
||||
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
|
||||
/* Look in interface-specific leasefile first for backwards compat */
|
||||
leasefile = get_dhclient_leasefile(AF_INET6,
|
||||
nm_dhcp_client_get_iface(client),
|
||||
nm_dhcp_client_get_uuid(client),
|
||||
client_config->uuid,
|
||||
NULL);
|
||||
if (leasefile) {
|
||||
_LOGD("looking for DUID in '%s'", leasefile);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
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,37 +265,30 @@ 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) {
|
||||
client_factory = _client_factory_available(_client_factory_find_by_name(client));
|
||||
if (!client_factory)
|
||||
nm_log_warn(LOGD_DHCP, "dhcp-init: DHCP client '%s' not available", client);
|
||||
}
|
||||
if (!client_factory) {
|
||||
client_factory = _client_factory_find_by_name("" NM_CONFIG_DEFAULT_MAIN_DHCP);
|
||||
if (!client_factory)
|
||||
nm_log_err(LOGD_DHCP,
|
||||
"dhcp-init: default DHCP client '%s' is not installed",
|
||||
NM_CONFIG_DEFAULT_MAIN_DHCP);
|
||||
else {
|
||||
client_factory = _client_factory_available(client_factory);
|
||||
if (!client_factory)
|
||||
nm_log_warn(LOGD_DHCP, "dhcp-init: DHCP client '%s' not available", client);
|
||||
nm_log_info(LOGD_DHCP,
|
||||
"dhcp-init: default DHCP client '%s' is not available",
|
||||
NM_CONFIG_DEFAULT_MAIN_DHCP);
|
||||
}
|
||||
if (!client_factory) {
|
||||
client_factory = _client_factory_find_by_name("" NM_CONFIG_DEFAULT_MAIN_DHCP);
|
||||
if (!client_factory)
|
||||
nm_log_err(LOGD_DHCP,
|
||||
"dhcp-init: default DHCP client '%s' is not installed",
|
||||
NM_CONFIG_DEFAULT_MAIN_DHCP);
|
||||
else {
|
||||
client_factory = _client_factory_available(client_factory);
|
||||
if (!client_factory)
|
||||
nm_log_info(LOGD_DHCP,
|
||||
"dhcp-init: default DHCP client '%s' is not available",
|
||||
NM_CONFIG_DEFAULT_MAIN_DHCP);
|
||||
}
|
||||
}
|
||||
if (!client_factory) {
|
||||
for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) {
|
||||
client_factory = _client_factory_available(_nm_dhcp_manager_factories[i]);
|
||||
if (client_factory)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!client_factory) {
|
||||
for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) {
|
||||
client_factory = _client_factory_available(_nm_dhcp_manager_factories[i]);
|
||||
if (client_factory)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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,23 +257,23 @@ lease_parse_address(NDhcp4ClientLease *lease,
|
|||
a_next_server.s_addr);
|
||||
}
|
||||
|
||||
nm_ip4_config_add_address(ip4_config,
|
||||
&((const NMPlatformIP4Address){
|
||||
.address = a_address.s_addr,
|
||||
.peer_address = a_address.s_addr,
|
||||
.plen = a_plen,
|
||||
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.timestamp = a_timestamp,
|
||||
.lifetime = a_lifetime,
|
||||
.preferred = a_lifetime,
|
||||
}));
|
||||
nm_l3_config_data_add_address_4(l3cd,
|
||||
&((const NMPlatformIP4Address){
|
||||
.address = a_address.s_addr,
|
||||
.peer_address = a_address.s_addr,
|
||||
.plen = a_plen,
|
||||
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.timestamp = a_timestamp,
|
||||
.lifetime = a_lifetime,
|
||||
.preferred = a_lifetime,
|
||||
}));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
lease_parse_address_list(NDhcp4ClientLease * lease,
|
||||
NMIP4Config * ip4_config,
|
||||
NML3ConfigData * l3cd,
|
||||
NMDhcpOptionDhcp4Options option,
|
||||
GHashTable * options,
|
||||
NMStrBuf * sbuf)
|
||||
|
|
@ -304,13 +305,13 @@ lease_parse_address_list(NDhcp4ClientLease * lease,
|
|||
* See https://github.com/systemd/systemd/issues/4524. */
|
||||
continue;
|
||||
}
|
||||
nm_ip4_config_add_nameserver(ip4_config, addr);
|
||||
nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr);
|
||||
break;
|
||||
case NM_DHCP_OPTION_DHCP4_NIS_SERVERS:
|
||||
nm_ip4_config_add_nis_server(ip4_config, addr);
|
||||
nm_l3_config_data_add_nis_server(l3cd, addr);
|
||||
break;
|
||||
case NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER:
|
||||
nm_ip4_config_add_wins(ip4_config, addr);
|
||||
nm_l3_config_data_add_wins(l3cd, addr);
|
||||
break;
|
||||
case NM_DHCP_OPTION_DHCP4_NTP_SERVER:
|
||||
break;
|
||||
|
|
@ -324,10 +325,8 @@ lease_parse_address_list(NDhcp4ClientLease * lease,
|
|||
|
||||
static void
|
||||
lease_parse_routes(NDhcp4ClientLease *lease,
|
||||
NMIP4Config * ip4_config,
|
||||
NML3ConfigData * l3cd,
|
||||
GHashTable * options,
|
||||
guint32 route_table,
|
||||
guint32 route_metric,
|
||||
NMStrBuf * sbuf)
|
||||
{
|
||||
char dest_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
|
|
@ -336,9 +335,9 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
|||
in_addr_t gateway;
|
||||
uint8_t plen;
|
||||
guint32 m;
|
||||
gboolean has_router_from_classless = FALSE;
|
||||
gboolean has_classless = FALSE;
|
||||
guint32 default_route_metric = route_metric;
|
||||
gboolean has_router_from_classless = FALSE;
|
||||
gboolean has_classless = FALSE;
|
||||
guint32 default_route_metric_offset = 0;
|
||||
const guint8 *l_data;
|
||||
gsize l_data_len;
|
||||
int r;
|
||||
|
|
@ -367,26 +366,22 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
|||
if (plen == 0) {
|
||||
/* if there are multiple default routes, we add them with differing
|
||||
* metrics. */
|
||||
m = default_route_metric;
|
||||
if (default_route_metric < G_MAXUINT32)
|
||||
default_route_metric++;
|
||||
|
||||
m = default_route_metric_offset++;
|
||||
has_router_from_classless = TRUE;
|
||||
} else {
|
||||
m = route_metric;
|
||||
}
|
||||
} else
|
||||
m = 0;
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
&((const NMPlatformIP4Route){
|
||||
.network = dest,
|
||||
.plen = plen,
|
||||
.gateway = gateway,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.metric = m,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
}),
|
||||
NULL);
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.network = dest,
|
||||
.plen = plen,
|
||||
.gateway = gateway,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
}));
|
||||
}
|
||||
|
||||
has_classless = TRUE;
|
||||
|
|
@ -419,17 +414,17 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
|||
continue;
|
||||
}
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
&((const NMPlatformIP4Route){
|
||||
.network = dest,
|
||||
.plen = plen,
|
||||
.gateway = gateway,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.metric = route_metric,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
}),
|
||||
NULL);
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.network = dest,
|
||||
.plen = plen,
|
||||
.gateway = gateway,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = 0,
|
||||
}));
|
||||
}
|
||||
|
||||
nm_dhcp_option_add_option(options,
|
||||
|
|
@ -463,19 +458,17 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
|||
|
||||
/* if there are multiple default routes, we add them with differing
|
||||
* metrics. */
|
||||
m = default_route_metric;
|
||||
if (default_route_metric < G_MAXUINT32)
|
||||
default_route_metric++;
|
||||
m = default_route_metric_offset++;
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.gateway = gateway,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
.metric = m,
|
||||
}),
|
||||
NULL);
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.gateway = gateway,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
}));
|
||||
}
|
||||
|
||||
nm_dhcp_option_add_option(options,
|
||||
|
|
@ -486,7 +479,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
|
|||
}
|
||||
|
||||
static void
|
||||
lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options)
|
||||
lease_parse_search_domains(NDhcp4ClientLease *lease, NML3ConfigData *l3cd, GHashTable *options)
|
||||
{
|
||||
gs_strfreev char **domains = NULL;
|
||||
const guint8 * l_data;
|
||||
|
|
@ -504,7 +497,7 @@ lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GH
|
|||
return;
|
||||
|
||||
for (i = 0; domains[i]; i++)
|
||||
nm_ip4_config_add_search(ip4_config, domains[i]);
|
||||
nm_l3_config_data_add_search(l3cd, AF_INET, domains[i]);
|
||||
|
||||
nm_dhcp_option_take_option(options,
|
||||
AF_INET,
|
||||
|
|
@ -539,34 +532,31 @@ lease_parse_private_options(NDhcp4ClientLease *lease, GHashTable *options)
|
|||
}
|
||||
}
|
||||
|
||||
static NMIP4Config *
|
||||
static NML3ConfigData *
|
||||
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
||||
const char * iface,
|
||||
int ifindex,
|
||||
NDhcp4ClientLease *lease,
|
||||
guint32 route_table,
|
||||
guint32 route_metric,
|
||||
GHashTable ** out_options,
|
||||
GError ** error)
|
||||
{
|
||||
nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE);
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE);
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
const guint8 * l_data;
|
||||
gsize l_data_len;
|
||||
const char * v_str;
|
||||
guint16 v_u16;
|
||||
gboolean v_bool;
|
||||
in_addr_t v_inaddr;
|
||||
struct in_addr v_inaddr_s;
|
||||
int r;
|
||||
|
||||
g_return_val_if_fail(lease != NULL, NULL);
|
||||
|
||||
ip4_config = nm_ip4_config_new(multi_idx, ifindex);
|
||||
options = nm_dhcp_option_create_options_dict();
|
||||
l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
|
||||
if (!lease_parse_address(lease, ip4_config, options, error))
|
||||
options = nm_dhcp_option_create_options_dict();
|
||||
|
||||
if (!lease_parse_address(lease, l3cd, options, error))
|
||||
return NULL;
|
||||
|
||||
r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s);
|
||||
|
|
@ -585,13 +575,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
v_inaddr);
|
||||
}
|
||||
|
||||
lease_parse_routes(lease, ip4_config, options, route_table, route_metric, &sbuf);
|
||||
lease_parse_routes(lease, l3cd, options, &sbuf);
|
||||
|
||||
lease_parse_address_list(lease,
|
||||
ip4_config,
|
||||
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
|
||||
options,
|
||||
&sbuf);
|
||||
lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, options, &sbuf);
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, &l_data, &l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
|
|
@ -616,7 +602,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
nm_str_buf_append_required_delimiter(&sbuf, ' ');
|
||||
nm_str_buf_append(&sbuf, s);
|
||||
nm_ip4_config_add_domain(ip4_config, s);
|
||||
nm_l3_config_data_add_domain(l3cd, AF_INET, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -628,18 +614,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
}
|
||||
}
|
||||
|
||||
lease_parse_search_domains(lease, ip4_config, options);
|
||||
lease_parse_search_domains(lease, l3cd, options);
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &l_data, &l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_mtu(l_data, l_data_len, &v_u16)) {
|
||||
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, v_u16);
|
||||
nm_ip4_config_set_mtu(ip4_config, v_u16, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
nm_l3_config_data_set_mtu(l3cd, v_u16);
|
||||
}
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, &l_data, &l_data_len);
|
||||
v_bool =
|
||||
(r == 0) && memmem(l_data, l_data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED"));
|
||||
nm_ip4_config_set_metered(ip4_config, v_bool);
|
||||
if ((r == 0) && memmem(l_data, l_data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
|
||||
nm_l3_config_data_set_metered(l3cd, TRUE);
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_HOST_NAME, &l_data, &l_data_len);
|
||||
if (r == 0) {
|
||||
|
|
@ -650,7 +635,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
}
|
||||
}
|
||||
|
||||
lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
|
||||
lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROOT_PATH, &l_data, &l_data_len);
|
||||
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
|
|
@ -681,11 +666,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
* We reject NUL characters inside the string (except trailing NULs).
|
||||
* Otherwise, we allow any encoding and backslash-escape the result to
|
||||
* UTF-8. */
|
||||
nm_dhcp_option_add_option_utf8safe_escape(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
|
||||
l_data,
|
||||
l_data_len);
|
||||
gs_free char *to_free = NULL;
|
||||
const char * escaped;
|
||||
|
||||
escaped = nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
|
||||
escaped ?: "");
|
||||
|
||||
nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
|
||||
nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
|
||||
}
|
||||
|
||||
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, &l_data, &l_data_len);
|
||||
|
|
@ -700,7 +691,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
&to_free);
|
||||
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, v_str ?: "");
|
||||
nm_ip4_config_set_nis_domain(ip4_config, v_str ?: "");
|
||||
nm_l3_config_data_set_nis_domain(l3cd, v_str ?: "");
|
||||
}
|
||||
|
||||
r = n_dhcp4_client_lease_get_file(lease, &v_str);
|
||||
|
|
@ -728,18 +719,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
v_str ?: "");
|
||||
}
|
||||
|
||||
lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
|
||||
lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
|
||||
|
||||
lease_parse_address_list(lease,
|
||||
ip4_config,
|
||||
NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER,
|
||||
options,
|
||||
&sbuf);
|
||||
lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, options, &sbuf);
|
||||
|
||||
lease_parse_private_options(lease, options);
|
||||
|
||||
NM_SET_OUT(out_options, g_steal_pointer(&options));
|
||||
return g_steal_pointer(&ip4_config);
|
||||
nm_dhcp_option_add_requests_to_options(options, AF_INET);
|
||||
|
||||
nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
|
||||
|
||||
return g_steal_pointer(&l3cd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -771,47 +761,44 @@ lease_save(NMDhcpNettools *self, NDhcp4ClientLease *lease, const char *lease_fil
|
|||
static void
|
||||
bound4_handle(NMDhcpNettools *self, NDhcp4ClientLease *lease, gboolean extended)
|
||||
{
|
||||
NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
|
||||
const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
GError * error = NULL;
|
||||
NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
|
||||
NMDhcpClient * client = NM_DHCP_CLIENT(self);
|
||||
const NMDhcpClientConfig *client_config;
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
GError * error = NULL;
|
||||
|
||||
_LOGT("lease available (%s)", extended ? "extended" : "new");
|
||||
|
||||
ip4_config = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
|
||||
iface,
|
||||
nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
|
||||
lease,
|
||||
nm_dhcp_client_get_route_table(NM_DHCP_CLIENT(self)),
|
||||
nm_dhcp_client_get_route_metric(NM_DHCP_CLIENT(self)),
|
||||
&options,
|
||||
&error);
|
||||
if (!ip4_config) {
|
||||
_LOGW("%s", error->message);
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(client),
|
||||
client_config->iface,
|
||||
nm_dhcp_client_get_ifindex(client),
|
||||
lease,
|
||||
&error);
|
||||
if (!l3cd) {
|
||||
_LOGW("failure to parse lease: %s", error->message);
|
||||
g_clear_error(&error);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_dhcp_option_add_requests_to_options(options, AF_INET);
|
||||
lease_save(self, lease, priv->lease_file);
|
||||
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
|
||||
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
|
||||
NM_IP_CONFIG_CAST(ip4_config),
|
||||
options);
|
||||
l3cd);
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
|
||||
{
|
||||
NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
|
||||
struct in_addr server_id;
|
||||
char addr_str[INET_ADDRSTRLEN];
|
||||
int r;
|
||||
NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
|
||||
const NMDhcpClientConfig *client_config;
|
||||
struct in_addr server_id;
|
||||
char addr_str[INET_ADDRSTRLEN];
|
||||
int r;
|
||||
|
||||
_LOGT("client event %d", event->event);
|
||||
client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self));
|
||||
|
||||
switch (event->event) {
|
||||
case N_DHCP4_CLIENT_EVENT_OFFER:
|
||||
|
|
@ -835,10 +822,10 @@ dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
|
|||
break;
|
||||
case N_DHCP4_CLIENT_EVENT_RETRACTED:
|
||||
case N_DHCP4_CLIENT_EVENT_EXPIRED:
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_EXPIRE, NULL, NULL);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_EXPIRE, NULL);
|
||||
break;
|
||||
case N_DHCP4_CLIENT_EVENT_CANCELLED:
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
break;
|
||||
case N_DHCP4_CLIENT_EVENT_GRANTED:
|
||||
priv->lease = n_dhcp4_client_lease_ref(event->granted.lease);
|
||||
|
|
@ -861,7 +848,7 @@ dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
|
|||
NULL,
|
||||
NULL,
|
||||
"dhcp4 (%s): %s",
|
||||
nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self)),
|
||||
client_config->iface,
|
||||
event->log.message);
|
||||
}
|
||||
} break;
|
||||
|
|
@ -890,13 +877,12 @@ dhcp4_event_cb(int fd, GIOCondition condition, gpointer user_data)
|
|||
*/
|
||||
_LOGE("error %d dispatching events", r);
|
||||
nm_clear_g_source_inst(&priv->event_source);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
while (!n_dhcp4_client_pop_event(priv->client, &event) && event) {
|
||||
while (!n_dhcp4_client_pop_event(priv->client, &event) && event)
|
||||
dhcp4_event_handle(self, event);
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
|
@ -914,23 +900,26 @@ nettools_create(NMDhcpNettools *self, GError **error)
|
|||
gsize hwaddr_len;
|
||||
gsize bcast_hwaddr_len;
|
||||
GBytes * client_id;
|
||||
gs_unref_bytes GBytes *client_id_new = NULL;
|
||||
const uint8_t * client_id_arr;
|
||||
size_t client_id_len;
|
||||
int r, fd, arp_type, transport;
|
||||
gs_unref_bytes GBytes * client_id_new = NULL;
|
||||
const uint8_t * client_id_arr;
|
||||
size_t client_id_len;
|
||||
int r, fd, arp_type, transport;
|
||||
const NMDhcpClientConfig *client_config;
|
||||
|
||||
client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self));
|
||||
|
||||
g_return_val_if_fail(!priv->client, FALSE);
|
||||
|
||||
/* TODO: honor nm_dhcp_client_get_anycast_address() */
|
||||
|
||||
hwaddr = nm_dhcp_client_get_hw_addr(NM_DHCP_CLIENT(self));
|
||||
hwaddr = client_config->hwaddr;
|
||||
if (!hwaddr || !(hwaddr_arr = g_bytes_get_data(hwaddr, &hwaddr_len))
|
||||
|| (arp_type = nm_utils_arp_type_detect_from_hwaddrlen(hwaddr_len)) < 0) {
|
||||
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bcast_hwaddr = nm_dhcp_client_get_broadcast_hw_addr(NM_DHCP_CLIENT(self));
|
||||
bcast_hwaddr = client_config->bcast_hwaddr;
|
||||
bcast_hwaddr_arr = g_bytes_get_data(bcast_hwaddr, &bcast_hwaddr_len);
|
||||
|
||||
switch (arp_type) {
|
||||
|
|
@ -947,7 +936,7 @@ nettools_create(NMDhcpNettools *self, GError **error)
|
|||
|
||||
/* Note that we always set a client-id. In particular for infiniband that is necessary,
|
||||
* see https://tools.ietf.org/html/rfc4390#section-2.1 . */
|
||||
client_id = nm_dhcp_client_get_client_id(NM_DHCP_CLIENT(self));
|
||||
client_id = client_config->client_id;
|
||||
if (!client_id) {
|
||||
client_id_new = nm_utils_dhcp_client_id_mac(arp_type, hwaddr_arr, hwaddr_len);
|
||||
client_id = client_id_new;
|
||||
|
|
@ -971,10 +960,7 @@ nettools_create(NMDhcpNettools *self, GError **error)
|
|||
n_dhcp4_client_config_set_transport(config, transport);
|
||||
n_dhcp4_client_config_set_mac(config, hwaddr_arr, hwaddr_len);
|
||||
n_dhcp4_client_config_set_broadcast_mac(config, bcast_hwaddr_arr, bcast_hwaddr_len);
|
||||
n_dhcp4_client_config_set_request_broadcast(
|
||||
config,
|
||||
NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
|
||||
NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST));
|
||||
n_dhcp4_client_config_set_request_broadcast(config, client_config->v4.request_broadcast);
|
||||
r = n_dhcp4_client_config_set_client_id(config,
|
||||
client_id_arr,
|
||||
NM_MIN(client_id_len, 1 + _NM_MAX_CLIENT_ID_LEN));
|
||||
|
|
@ -1033,7 +1019,7 @@ decline(NMDhcpClient *client, const char *error_message, GError **error)
|
|||
|
||||
g_return_val_if_fail(priv->lease, FALSE);
|
||||
|
||||
_LOGT("dhcp4-client: decline");
|
||||
_LOGT("dhcp4-client: decline (%s)", error_message);
|
||||
|
||||
r = n_dhcp4_client_lease_decline(priv->lease, error_message);
|
||||
if (r) {
|
||||
|
|
@ -1063,19 +1049,20 @@ fqdn_flags_to_wire(NMDhcpHostnameFlags flags)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
||||
ip4_start(NMDhcpClient *client, GError **error)
|
||||
{
|
||||
nm_auto(n_dhcp4_client_probe_config_freep) NDhcp4ClientProbeConfig *config = NULL;
|
||||
NMDhcpNettools * self = NM_DHCP_NETTOOLS(client);
|
||||
NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
|
||||
gs_free char * lease_file = NULL;
|
||||
struct in_addr last_addr = {0};
|
||||
const char * hostname;
|
||||
const char * mud_url;
|
||||
GBytes * vendor_class_identifier;
|
||||
int r, i;
|
||||
NMDhcpNettools * self = NM_DHCP_NETTOOLS(client);
|
||||
NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
|
||||
const NMDhcpClientConfig *client_config;
|
||||
gs_free char * lease_file = NULL;
|
||||
struct in_addr last_addr = {0};
|
||||
int r, i;
|
||||
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
|
||||
g_return_val_if_fail(!priv->probe, FALSE);
|
||||
g_return_val_if_fail(client_config, FALSE);
|
||||
|
||||
if (!nettools_create(self, error))
|
||||
return FALSE;
|
||||
|
|
@ -1094,12 +1081,12 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
|||
|
||||
nm_dhcp_utils_get_leasefile_path(AF_INET,
|
||||
"internal",
|
||||
nm_dhcp_client_get_iface(client),
|
||||
nm_dhcp_client_get_uuid(client),
|
||||
client_config->iface,
|
||||
client_config->uuid,
|
||||
&lease_file);
|
||||
|
||||
if (last_ip4_address)
|
||||
inet_pton(AF_INET, last_ip4_address, &last_addr);
|
||||
if (client_config->v4.last_address)
|
||||
inet_pton(AF_INET, client_config->v4.last_address, &last_addr);
|
||||
else {
|
||||
/*
|
||||
* TODO: we stick to the systemd-networkd lease file format. Quite easy for now to
|
||||
|
|
@ -1129,31 +1116,33 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
|||
}
|
||||
}
|
||||
|
||||
mud_url = nm_dhcp_client_get_mud_url(client);
|
||||
if (mud_url) {
|
||||
if (client_config->mud_url) {
|
||||
r = n_dhcp4_client_probe_config_append_option(config,
|
||||
NM_DHCP_OPTION_DHCP4_MUD_URL,
|
||||
mud_url,
|
||||
strlen(mud_url));
|
||||
client_config->mud_url,
|
||||
strlen(client_config->mud_url));
|
||||
if (r) {
|
||||
set_error_nettools(error, r, "failed to set MUD URL");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
hostname = nm_dhcp_client_get_hostname(client);
|
||||
if (hostname) {
|
||||
if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN)) {
|
||||
|
||||
if (client_config->hostname) {
|
||||
if (client_config->use_fqdn) {
|
||||
uint8_t buffer[255];
|
||||
NMDhcpHostnameFlags flags;
|
||||
size_t fqdn_len;
|
||||
|
||||
flags = nm_dhcp_client_get_hostname_flags(client);
|
||||
flags = client_config->hostname_flags;
|
||||
buffer[0] = fqdn_flags_to_wire(flags);
|
||||
buffer[1] = 0; /* RCODE1 (deprecated) */
|
||||
buffer[2] = 0; /* RCODE2 (deprecated) */
|
||||
|
||||
if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) {
|
||||
r = nm_sd_dns_name_to_wire_format(hostname, buffer + 3, sizeof(buffer) - 3, FALSE);
|
||||
r = nm_sd_dns_name_to_wire_format(client_config->hostname,
|
||||
buffer + 3,
|
||||
sizeof(buffer) - 3,
|
||||
FALSE);
|
||||
if (r <= 0) {
|
||||
if (r < 0)
|
||||
nm_utils_error_set_errno(error, r, "failed to convert DHCP FQDN: %s");
|
||||
|
|
@ -1163,12 +1152,12 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
|||
}
|
||||
fqdn_len = r;
|
||||
} else {
|
||||
fqdn_len = strlen(hostname);
|
||||
fqdn_len = strlen(client_config->hostname);
|
||||
if (fqdn_len > sizeof(buffer) - 3) {
|
||||
nm_utils_error_set(error, r, "failed to set DHCP FQDN: name too long");
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(buffer + 3, hostname, fqdn_len);
|
||||
memcpy(buffer + 3, client_config->hostname, fqdn_len);
|
||||
}
|
||||
|
||||
r = n_dhcp4_client_probe_config_append_option(config,
|
||||
|
|
@ -1182,8 +1171,8 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
|||
} else {
|
||||
r = n_dhcp4_client_probe_config_append_option(config,
|
||||
NM_DHCP_OPTION_DHCP4_HOST_NAME,
|
||||
hostname,
|
||||
strlen(hostname));
|
||||
client_config->hostname,
|
||||
strlen(client_config->hostname));
|
||||
if (r) {
|
||||
set_error_nettools(error, r, "failed to set DHCP hostname");
|
||||
return FALSE;
|
||||
|
|
@ -1191,12 +1180,11 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
|||
}
|
||||
}
|
||||
|
||||
vendor_class_identifier = nm_dhcp_client_get_vendor_class_identifier(client);
|
||||
if (vendor_class_identifier) {
|
||||
if (client_config->vendor_class_identifier) {
|
||||
const void *option_data;
|
||||
gsize option_size;
|
||||
|
||||
option_data = g_bytes_get_data(vendor_class_identifier, &option_size);
|
||||
option_data = g_bytes_get_data(client_config->vendor_class_identifier, &option_size);
|
||||
nm_assert(option_data);
|
||||
nm_assert(option_size <= 255);
|
||||
|
||||
|
|
@ -1220,8 +1208,6 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
|||
}
|
||||
|
||||
_LOGT("dhcp-client4: start " NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(priv->client));
|
||||
|
||||
nm_dhcp_client_start_timeout(client);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "libnm-std-aux/unaligned.h"
|
||||
|
||||
#include "nm-utils.h"
|
||||
#include "nm-l3-config-data.h"
|
||||
#include "nm-dhcp-utils.h"
|
||||
#include "nm-dhcp-options.h"
|
||||
#include "nm-core-utils.h"
|
||||
|
|
@ -51,8 +52,6 @@ typedef struct {
|
|||
char * lease_file;
|
||||
|
||||
guint request_count;
|
||||
|
||||
bool privacy : 1;
|
||||
} NMDhcpSystemdPrivate;
|
||||
|
||||
struct _NMDhcpSystemd {
|
||||
|
|
@ -70,18 +69,15 @@ G_DEFINE_TYPE(NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NMIP4Config *
|
||||
static NML3ConfigData *
|
||||
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
||||
const char * iface,
|
||||
int ifindex,
|
||||
sd_dhcp_lease * lease,
|
||||
guint32 route_table,
|
||||
guint32 route_metric,
|
||||
GHashTable ** out_options,
|
||||
GError ** error)
|
||||
{
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
const struct in_addr * addr_list;
|
||||
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
const char * s;
|
||||
|
|
@ -92,7 +88,6 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
int i, num;
|
||||
const void * data;
|
||||
gsize data_len;
|
||||
gboolean metered = FALSE;
|
||||
gboolean has_router_from_classless = FALSE;
|
||||
gboolean has_classless_route = FALSE;
|
||||
gboolean has_static_route = FALSE;
|
||||
|
|
@ -133,9 +128,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ip4_config = nm_ip4_config_new(multi_idx, ifindex);
|
||||
l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
|
||||
options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
|
||||
options = nm_dhcp_option_create_options_dict();
|
||||
|
||||
_nm_utils_inet4_ntop(a_address.s_addr, addr_str);
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str);
|
||||
|
|
@ -160,16 +155,16 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, addr_str);
|
||||
}
|
||||
|
||||
nm_ip4_config_add_address(ip4_config,
|
||||
&((const NMPlatformIP4Address){
|
||||
.address = a_address.s_addr,
|
||||
.peer_address = a_address.s_addr,
|
||||
.plen = a_plen,
|
||||
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.timestamp = ts,
|
||||
.lifetime = a_lifetime,
|
||||
.preferred = a_lifetime,
|
||||
}));
|
||||
nm_l3_config_data_add_address_4(l3cd,
|
||||
&((const NMPlatformIP4Address){
|
||||
.address = a_address.s_addr,
|
||||
.peer_address = a_address.s_addr,
|
||||
.plen = a_plen,
|
||||
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.timestamp = ts,
|
||||
.lifetime = a_lifetime,
|
||||
.preferred = a_lifetime,
|
||||
}));
|
||||
|
||||
if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) {
|
||||
_nm_utils_inet4_ntop(server_id.s_addr, addr_str);
|
||||
|
|
@ -193,7 +188,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
* See https://github.com/systemd/systemd/issues/4524. */
|
||||
continue;
|
||||
}
|
||||
nm_ip4_config_add_nameserver(ip4_config, addr_list[i].s_addr);
|
||||
nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr_list[i].s_addr);
|
||||
}
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
|
|
@ -206,7 +201,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
g_string_append(nm_gstring_add_space_delimiter(str), search_domains[i]);
|
||||
nm_ip4_config_add_search(ip4_config, search_domains[i]);
|
||||
nm_l3_config_data_add_search(l3cd, AF_INET, search_domains[i]);
|
||||
}
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
|
|
@ -224,7 +219,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
* As systemd escapes such characters, split them at \\032. */
|
||||
domains = g_strsplit(s, "\\032", 0);
|
||||
for (d = domains; *d; d++)
|
||||
nm_ip4_config_add_domain(ip4_config, *d);
|
||||
nm_l3_config_data_add_domain(l3cd, AF_INET, *d);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) {
|
||||
|
|
@ -233,9 +228,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
num = sd_dhcp_lease_get_routes(lease, &routes);
|
||||
if (num > 0) {
|
||||
nm_auto_free_gstring GString *str_classless = NULL;
|
||||
nm_auto_free_gstring GString *str_static = NULL;
|
||||
guint32 default_route_metric = route_metric;
|
||||
nm_auto_free_gstring GString *str_classless = NULL;
|
||||
nm_auto_free_gstring GString *str_static = NULL;
|
||||
guint32 default_route_metric_offset = 0;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
switch (sd_dhcp_route_get_option(routes[i])) {
|
||||
|
|
@ -307,25 +302,22 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
if (r_plen == 0) {
|
||||
/* if there are multiple default routes, we add them with differing
|
||||
* metrics. */
|
||||
m = default_route_metric;
|
||||
if (default_route_metric < G_MAXUINT32)
|
||||
default_route_metric++;
|
||||
|
||||
m = default_route_metric_offset++;
|
||||
has_router_from_classless = TRUE;
|
||||
} else
|
||||
m = route_metric;
|
||||
m = 0;
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
&((const NMPlatformIP4Route){
|
||||
.network = network_net,
|
||||
.plen = r_plen,
|
||||
.gateway = r_gateway.s_addr,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.metric = m,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
}),
|
||||
NULL);
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.network = network_net,
|
||||
.plen = r_plen,
|
||||
.gateway = r_gateway.s_addr,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
}));
|
||||
}
|
||||
|
||||
if (str_classless && str_classless->len > 0)
|
||||
|
|
@ -342,7 +334,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
num = sd_dhcp_lease_get_router(lease, &a_router);
|
||||
if (num > 0) {
|
||||
guint32 default_route_metric = route_metric;
|
||||
guint32 default_route_metric_offset = 0;
|
||||
|
||||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
|
|
@ -368,26 +360,24 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
/* if there are multiple default routes, we add them with differing
|
||||
* metrics. */
|
||||
m = default_route_metric;
|
||||
if (default_route_metric < G_MAXUINT32)
|
||||
default_route_metric++;
|
||||
m = default_route_metric_offset++;
|
||||
|
||||
nm_ip4_config_add_route(
|
||||
ip4_config,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.gateway = a_router[i].s_addr,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
.metric = m,
|
||||
}),
|
||||
NULL);
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.gateway = a_router[i].s_addr,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
}));
|
||||
}
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROUTER, str->str);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_mtu(lease, &mtu) >= 0 && mtu) {
|
||||
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, mtu);
|
||||
nm_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
nm_l3_config_data_set_mtu(l3cd, mtu);
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_ntp(lease, &addr_list);
|
||||
|
|
@ -422,9 +412,10 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, s);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0)
|
||||
metered = !!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED"));
|
||||
nm_ip4_config_set_metered(ip4_config, metered);
|
||||
if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0) {
|
||||
if (!!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
|
||||
nm_l3_config_data_set_metered(l3cd, TRUE);
|
||||
}
|
||||
|
||||
num = nm_sd_dhcp_lease_get_private_options(lease, &private_options);
|
||||
if (num > 0) {
|
||||
|
|
@ -436,12 +427,18 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY) {
|
||||
if (nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
nm_dhcp_option_add_option_utf8safe_escape(
|
||||
options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
|
||||
l_data,
|
||||
l_data_len);
|
||||
gs_free char *to_free = NULL;
|
||||
const char * escaped;
|
||||
|
||||
escaped =
|
||||
nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
|
||||
escaped ?: "");
|
||||
|
||||
nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
|
||||
nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -458,8 +455,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
nm_dhcp_option_take_option(options, AF_INET, code, option_string);
|
||||
}
|
||||
}
|
||||
NM_SET_OUT(out_options, g_steal_pointer(&options));
|
||||
return g_steal_pointer(&ip4_config);
|
||||
|
||||
nm_dhcp_option_add_requests_to_options(options, AF_INET);
|
||||
|
||||
nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
|
||||
|
||||
return g_steal_pointer(&l3cd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -467,43 +468,37 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
|||
static void
|
||||
bound4_handle(NMDhcpSystemd *self, gboolean extended)
|
||||
{
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
sd_dhcp_lease * lease = NULL;
|
||||
GError * error = NULL;
|
||||
NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
sd_dhcp_lease * lease = NULL;
|
||||
GError * error = NULL;
|
||||
|
||||
if (sd_dhcp_client_get_lease(priv->client4, &lease) < 0 || !lease) {
|
||||
_LOGW("no lease!");
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGD("lease available");
|
||||
|
||||
ip4_config = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
|
||||
iface,
|
||||
nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
|
||||
lease,
|
||||
nm_dhcp_client_get_route_table(NM_DHCP_CLIENT(self)),
|
||||
nm_dhcp_client_get_route_metric(NM_DHCP_CLIENT(self)),
|
||||
&options,
|
||||
&error);
|
||||
if (!ip4_config) {
|
||||
l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
|
||||
iface,
|
||||
nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
|
||||
lease,
|
||||
&error);
|
||||
if (!l3cd) {
|
||||
_LOGW("%s", error->message);
|
||||
g_clear_error(&error);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_dhcp_option_add_requests_to_options(options, AF_INET);
|
||||
dhcp_lease_save(lease, priv->lease_file);
|
||||
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
|
||||
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
|
||||
NM_IP_CONFIG_CAST(ip4_config),
|
||||
options);
|
||||
l3cd);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -522,10 +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);
|
||||
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) {
|
||||
|
|
@ -755,36 +752,35 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
nm_dhcp_client_start_timeout(client);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NMIP6Config *
|
||||
static NML3ConfigData *
|
||||
lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
|
||||
const char * iface,
|
||||
int ifindex,
|
||||
sd_dhcp6_lease * lease,
|
||||
gboolean info_only,
|
||||
GHashTable ** out_options,
|
||||
gint32 ts,
|
||||
GError ** error)
|
||||
{
|
||||
gs_unref_object NMIP6Config *ip6_config = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
struct in6_addr tmp_addr;
|
||||
const struct in6_addr * dns;
|
||||
uint32_t lft_pref, lft_valid;
|
||||
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
char ** domains;
|
||||
const char * s;
|
||||
nm_auto_free_gstring GString *str = NULL;
|
||||
nm_auto_free_gstring GString *str = NULL;
|
||||
gboolean has_any_addresses = FALSE;
|
||||
int num, i;
|
||||
|
||||
nm_assert(lease);
|
||||
|
||||
ip6_config = nm_ip6_config_new(multi_idx, ifindex);
|
||||
l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
|
||||
options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
|
||||
options = nm_dhcp_option_create_options_dict();
|
||||
|
||||
sd_dhcp6_lease_reset_address_iter(lease);
|
||||
nm_gstring_prepare(&str);
|
||||
|
|
@ -798,15 +794,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 +820,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 +830,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 +839,48 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
|
|||
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_FQDN, s);
|
||||
}
|
||||
|
||||
NM_SET_OUT(out_options, g_steal_pointer(&options));
|
||||
return g_steal_pointer(&ip6_config);
|
||||
nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET6, g_steal_pointer(&options));
|
||||
|
||||
return g_steal_pointer(&l3cd);
|
||||
}
|
||||
|
||||
static void
|
||||
bound6_handle(NMDhcpSystemd *self)
|
||||
{
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
|
||||
const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
|
||||
gs_unref_object NMIP6Config *ip6_config = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
NMPlatformIP6Address prefix = {0};
|
||||
sd_dhcp6_lease * lease = NULL;
|
||||
NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
|
||||
const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
|
||||
const NMDhcpClientConfig *client_config;
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
NMPlatformIP6Address prefix = {0};
|
||||
sd_dhcp6_lease * lease = NULL;
|
||||
|
||||
client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self));
|
||||
|
||||
if (sd_dhcp6_client_get_lease(priv->client6, &lease) < 0 || !lease) {
|
||||
_LOGW(" no lease!");
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGD("lease available");
|
||||
|
||||
ip6_config =
|
||||
lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
|
||||
iface,
|
||||
nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
|
||||
lease,
|
||||
NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
|
||||
NM_DHCP_CLIENT_FLAGS_INFO_ONLY),
|
||||
&options,
|
||||
ts,
|
||||
&error);
|
||||
l3cd = lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
|
||||
iface,
|
||||
nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
|
||||
lease,
|
||||
client_config->v6.info_only,
|
||||
ts,
|
||||
&error);
|
||||
|
||||
if (!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 +905,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 +922,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 +938,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 +956,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 +998,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 +1007,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 +1025,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");
|
||||
|
|
@ -1052,7 +1048,6 @@ ip6_start(NMDhcpClient * client,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
nm_dhcp_client_start_timeout(client);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
|
||||
|
||||
#include "nm-dhcp-utils.h"
|
||||
#include "nm-l3-config-data.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-config.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
|
@ -24,12 +25,10 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
ip4_process_dhcpcd_rfc3442_routes(const char * iface,
|
||||
const char * str,
|
||||
guint32 route_table,
|
||||
guint32 route_metric,
|
||||
NMIP4Config *ip4_config,
|
||||
guint32 * gwaddr)
|
||||
ip4_process_dhcpcd_rfc3442_routes(const char * iface,
|
||||
const char * str,
|
||||
NML3ConfigData *l3cd,
|
||||
guint32 * gwaddr)
|
||||
{
|
||||
gs_free const char **routes = NULL;
|
||||
const char ** r;
|
||||
|
|
@ -45,10 +44,9 @@ ip4_process_dhcpcd_rfc3442_routes(const char * iface,
|
|||
}
|
||||
|
||||
for (r = routes; *r; r += 2) {
|
||||
char * slash;
|
||||
NMPlatformIP4Route route;
|
||||
int rt_cidr = 32;
|
||||
guint32 rt_addr, rt_route;
|
||||
char * slash;
|
||||
int rt_cidr = 32;
|
||||
guint32 rt_addr, rt_route;
|
||||
|
||||
slash = strchr(*r, '/');
|
||||
if (slash) {
|
||||
|
|
@ -89,14 +87,18 @@ ip4_process_dhcpcd_rfc3442_routes(const char * iface,
|
|||
*r,
|
||||
rt_cidr,
|
||||
*(r + 1));
|
||||
memset(&route, 0, sizeof(route));
|
||||
route.network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr);
|
||||
route.plen = rt_cidr;
|
||||
route.gateway = rt_route;
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
|
||||
route.metric = route_metric;
|
||||
route.table_coerced = nm_platform_route_table_coerce(route_table);
|
||||
nm_ip4_config_add_route(ip4_config, &route, NULL);
|
||||
|
||||
nm_l3_config_data_add_route_4(
|
||||
l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr),
|
||||
.plen = rt_cidr,
|
||||
.gateway = rt_route,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.metric_any = TRUE,
|
||||
.table_any = TRUE,
|
||||
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,12 +155,10 @@ process_dhclient_rfc3442_route(const char *const **p_octets, NMPlatformIP4Route
|
|||
}
|
||||
|
||||
static gboolean
|
||||
ip4_process_dhclient_rfc3442_routes(const char * iface,
|
||||
const char * str,
|
||||
guint32 route_table,
|
||||
guint32 route_metric,
|
||||
NMIP4Config *ip4_config,
|
||||
guint32 * gwaddr)
|
||||
ip4_process_dhclient_rfc3442_routes(const char * iface,
|
||||
const char * str,
|
||||
NML3ConfigData *l3cd,
|
||||
guint32 * gwaddr)
|
||||
{
|
||||
gs_free const char **octets = NULL;
|
||||
const char *const * o;
|
||||
|
|
@ -189,9 +189,12 @@ ip4_process_dhclient_rfc3442_routes(const char * iface,
|
|||
|
||||
/* normal route */
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
|
||||
route.metric = route_metric;
|
||||
route.table_coerced = nm_platform_route_table_coerce(route_table);
|
||||
nm_ip4_config_add_route(ip4_config, &route, NULL);
|
||||
route.table_any = TRUE;
|
||||
route.table_coerced = 0;
|
||||
route.metric_any = TRUE;
|
||||
route.metric = 0;
|
||||
|
||||
nm_l3_config_data_add_route_4(l3cd, &route);
|
||||
|
||||
_LOG2I(LOGD_DHCP4,
|
||||
iface,
|
||||
|
|
@ -206,17 +209,15 @@ ip4_process_dhclient_rfc3442_routes(const char * iface,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
ip4_process_classless_routes(const char * iface,
|
||||
GHashTable * options,
|
||||
guint32 route_table,
|
||||
guint32 route_metric,
|
||||
NMIP4Config *ip4_config,
|
||||
guint32 * gwaddr)
|
||||
ip4_process_classless_routes(const char * iface,
|
||||
GHashTable * options,
|
||||
NML3ConfigData *l3cd,
|
||||
guint32 * gwaddr)
|
||||
{
|
||||
const char *str, *p;
|
||||
|
||||
g_return_val_if_fail(options != NULL, FALSE);
|
||||
g_return_val_if_fail(ip4_config != NULL, FALSE);
|
||||
g_return_val_if_fail(l3cd != NULL, FALSE);
|
||||
|
||||
*gwaddr = 0;
|
||||
|
||||
|
|
@ -265,28 +266,14 @@ ip4_process_classless_routes(const char * iface,
|
|||
|
||||
if (strchr(str, '/')) {
|
||||
/* dhcpcd format */
|
||||
return ip4_process_dhcpcd_rfc3442_routes(iface,
|
||||
str,
|
||||
route_table,
|
||||
route_metric,
|
||||
ip4_config,
|
||||
gwaddr);
|
||||
return ip4_process_dhcpcd_rfc3442_routes(iface, str, l3cd, gwaddr);
|
||||
}
|
||||
|
||||
return ip4_process_dhclient_rfc3442_routes(iface,
|
||||
str,
|
||||
route_table,
|
||||
route_metric,
|
||||
ip4_config,
|
||||
gwaddr);
|
||||
return ip4_process_dhclient_rfc3442_routes(iface, str, l3cd, gwaddr);
|
||||
}
|
||||
|
||||
static void
|
||||
process_classful_routes(const char * iface,
|
||||
GHashTable * options,
|
||||
guint32 route_table,
|
||||
guint32 route_metric,
|
||||
NMIP4Config *ip4_config)
|
||||
process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData *l3cd)
|
||||
{
|
||||
gs_free const char **searches = NULL;
|
||||
const char ** s;
|
||||
|
|
@ -320,8 +307,10 @@ process_classful_routes(const char * iface,
|
|||
|
||||
// FIXME: ensure the IP address and route are sane
|
||||
|
||||
memset(&route, 0, sizeof(route));
|
||||
route.network = rt_addr;
|
||||
route = (NMPlatformIP4Route){
|
||||
.network = rt_addr,
|
||||
};
|
||||
|
||||
/* RFC 2132, updated by RFC 3442:
|
||||
* The Static Routes option (option 33) does not provide a subnet mask
|
||||
* for each route - it is assumed that the subnet mask is implicit in
|
||||
|
|
@ -333,12 +322,15 @@ process_classful_routes(const char * iface,
|
|||
}
|
||||
route.gateway = rt_route;
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
|
||||
route.metric = route_metric;
|
||||
route.table_coerced = nm_platform_route_table_coerce(route_table);
|
||||
route.table_any = TRUE;
|
||||
route.table_coerced = 0;
|
||||
route.metric_any = TRUE;
|
||||
route.metric = 0;
|
||||
|
||||
route.network = nm_utils_ip4_address_clear_host_address(route.network, route.plen);
|
||||
|
||||
nm_ip4_config_add_route(ip4_config, &route, NULL);
|
||||
nm_l3_config_data_add_route_4(l3cd, &route);
|
||||
|
||||
_LOG2I(LOGD_DHCP,
|
||||
iface,
|
||||
" static route %s",
|
||||
|
|
@ -347,7 +339,7 @@ process_classful_routes(const char * iface,
|
|||
}
|
||||
|
||||
static void
|
||||
process_domain_search(const char *iface, const char *str, GFunc add_func, gpointer user_data)
|
||||
process_domain_search(int addr_family, const char *iface, const char *str, NML3ConfigData *l3cd)
|
||||
{
|
||||
gs_free const char **searches = NULL;
|
||||
gs_free char * unescaped = NULL;
|
||||
|
|
@ -356,7 +348,7 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint
|
|||
int i;
|
||||
|
||||
g_return_if_fail(str != NULL);
|
||||
g_return_if_fail(add_func != NULL);
|
||||
nm_assert(l3cd);
|
||||
|
||||
unescaped = g_strdup(str);
|
||||
|
||||
|
|
@ -379,46 +371,43 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint
|
|||
searches = nm_strsplit_set(unescaped, " ");
|
||||
for (s = searches; searches && *s; s++) {
|
||||
_LOG2I(LOGD_DHCP, iface, " domain search '%s'", *s);
|
||||
add_func((gpointer) *s, user_data);
|
||||
nm_l3_config_data_add_search(l3cd, addr_family, *s);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ip4_add_domain_search(gpointer data, gpointer user_data)
|
||||
{
|
||||
nm_ip4_config_add_search(NM_IP4_CONFIG(user_data), (const char *) data);
|
||||
}
|
||||
|
||||
NMIP4Config *
|
||||
NML3ConfigData *
|
||||
nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
||||
int ifindex,
|
||||
const char * iface,
|
||||
GHashTable * options,
|
||||
guint32 route_table,
|
||||
guint32 route_metric)
|
||||
GHashTable * options)
|
||||
{
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
guint32 tmp_addr;
|
||||
in_addr_t addr;
|
||||
NMPlatformIP4Address address;
|
||||
char * str = NULL;
|
||||
gboolean gateway_has = FALSE;
|
||||
guint32 gateway = 0;
|
||||
guint8 plen = 0;
|
||||
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
guint32 tmp_addr;
|
||||
in_addr_t addr;
|
||||
NMPlatformIP4Address address;
|
||||
char * str = NULL;
|
||||
gboolean gateway_has = FALSE;
|
||||
guint32 gateway = 0;
|
||||
guint8 plen = 0;
|
||||
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
guint32 now;
|
||||
|
||||
g_return_val_if_fail(options != NULL, NULL);
|
||||
|
||||
ip4_config = nm_ip4_config_new(multi_idx, ifindex);
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.timestamp = nm_utils_get_monotonic_timestamp_sec();
|
||||
l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
|
||||
now = nm_utils_get_monotonic_timestamp_sec();
|
||||
|
||||
address = (NMPlatformIP4Address){
|
||||
.timestamp = now,
|
||||
};
|
||||
|
||||
str = g_hash_table_lookup(options, "ip_address");
|
||||
if (str && (inet_pton(AF_INET, str, &addr) > 0))
|
||||
_LOG2I(LOGD_DHCP4, iface, " address %s", str);
|
||||
else
|
||||
if (!str || !nm_utils_parse_inaddr_bin(AF_INET, str, NULL, &addr))
|
||||
return NULL;
|
||||
|
||||
_LOG2I(LOGD_DHCP4, iface, " address %s", str);
|
||||
|
||||
str = g_hash_table_lookup(options, "subnet_mask");
|
||||
if (str && (inet_pton(AF_INET, str, &tmp_addr) > 0)) {
|
||||
plen = nm_utils_ip4_netmask_to_prefix(tmp_addr);
|
||||
|
|
@ -433,13 +422,8 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
/* Routes: if the server returns classless static routes, we MUST ignore
|
||||
* the 'static_routes' option.
|
||||
*/
|
||||
if (!ip4_process_classless_routes(iface,
|
||||
options,
|
||||
route_table,
|
||||
route_metric,
|
||||
ip4_config,
|
||||
&gateway))
|
||||
process_classful_routes(iface, options, route_table, route_metric, ip4_config);
|
||||
if (!ip4_process_classless_routes(iface, options, l3cd, &gateway))
|
||||
process_classful_routes(iface, options, l3cd);
|
||||
|
||||
if (gateway) {
|
||||
_LOG2I(LOGD_DHCP4, iface, " gateway %s", _nm_utils_inet4_ntop(gateway, sbuf));
|
||||
|
|
@ -453,7 +437,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
gs_free const char **routers = nm_strsplit_set(str, " ");
|
||||
const char ** s;
|
||||
|
||||
for (s = routers; routers && *s; s++) {
|
||||
for (s = routers; *s; s++) {
|
||||
/* FIXME: how to handle multiple routers? */
|
||||
if (inet_pton(AF_INET, *s, &gateway) > 0) {
|
||||
_LOG2I(LOGD_DHCP4, iface, " gateway %s", *s);
|
||||
|
|
@ -469,11 +453,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
const NMPlatformIP4Route r = {
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.gateway = gateway,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
.metric = route_metric,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = 0,
|
||||
};
|
||||
|
||||
nm_ip4_config_add_route(ip4_config, &r, NULL);
|
||||
nm_l3_config_data_add_route_4(l3cd, &r);
|
||||
}
|
||||
|
||||
str = g_hash_table_lookup(options, "dhcp_lease_time");
|
||||
|
|
@ -483,7 +469,8 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
}
|
||||
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_DHCP;
|
||||
nm_ip4_config_add_address(ip4_config, &address);
|
||||
|
||||
nm_l3_config_data_add_address_4(l3cd, &address);
|
||||
|
||||
str = g_hash_table_lookup(options, "host_name");
|
||||
if (str)
|
||||
|
|
@ -497,7 +484,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
for (s = dns; dns && *s; s++) {
|
||||
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
|
||||
if (tmp_addr) {
|
||||
nm_ip4_config_add_nameserver(ip4_config, tmp_addr);
|
||||
nm_l3_config_data_add_nameserver(l3cd, AF_INET, &tmp_addr);
|
||||
_LOG2I(LOGD_DHCP4, iface, " nameserver '%s'", *s);
|
||||
}
|
||||
} else
|
||||
|
|
@ -512,13 +499,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
for (s = domains; domains && *s; s++) {
|
||||
_LOG2I(LOGD_DHCP4, iface, " domain name '%s'", *s);
|
||||
nm_ip4_config_add_domain(ip4_config, *s);
|
||||
nm_l3_config_data_add_domain(l3cd, AF_INET, *s);
|
||||
}
|
||||
}
|
||||
|
||||
str = g_hash_table_lookup(options, "domain_search");
|
||||
if (str)
|
||||
process_domain_search(iface, str, ip4_add_domain_search, ip4_config);
|
||||
process_domain_search(AF_INET, iface, str, l3cd);
|
||||
|
||||
str = g_hash_table_lookup(options, "netbios_name_servers");
|
||||
if (str) {
|
||||
|
|
@ -528,7 +515,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
for (s = nbns; nbns && *s; s++) {
|
||||
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
|
||||
if (tmp_addr) {
|
||||
nm_ip4_config_add_wins(ip4_config, tmp_addr);
|
||||
nm_l3_config_data_add_wins(l3cd, tmp_addr);
|
||||
_LOG2I(LOGD_DHCP4, iface, " wins '%s'", *s);
|
||||
}
|
||||
} else
|
||||
|
|
@ -546,13 +533,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
return NULL;
|
||||
|
||||
if (int_mtu > 576)
|
||||
nm_ip4_config_set_mtu(ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
nm_l3_config_data_set_mtu(l3cd, int_mtu);
|
||||
}
|
||||
|
||||
str = g_hash_table_lookup(options, "nis_domain");
|
||||
if (str) {
|
||||
_LOG2I(LOGD_DHCP4, iface, " NIS domain '%s'", str);
|
||||
nm_ip4_config_set_nis_domain(ip4_config, str);
|
||||
nm_l3_config_data_add_domain(l3cd, AF_INET, str);
|
||||
}
|
||||
|
||||
str = g_hash_table_lookup(options, "nis_servers");
|
||||
|
|
@ -563,7 +550,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
for (s = nis; nis && *s; s++) {
|
||||
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
|
||||
if (tmp_addr) {
|
||||
nm_ip4_config_add_nis_server(ip4_config, tmp_addr);
|
||||
nm_l3_config_data_add_nis_server(l3cd, tmp_addr);
|
||||
_LOG2I(LOGD_DHCP4, iface, " nis '%s'", *s);
|
||||
}
|
||||
} else
|
||||
|
|
@ -572,19 +559,20 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
}
|
||||
|
||||
str = g_hash_table_lookup(options, "vendor_encapsulated_options");
|
||||
nm_ip4_config_set_metered(ip4_config, str && strstr(str, "ANDROID_METERED"));
|
||||
if (str && strstr(str, "ANDROID_METERED"))
|
||||
nm_l3_config_data_set_metered(l3cd, TRUE);
|
||||
|
||||
return g_steal_pointer(&ip4_config);
|
||||
str = g_hash_table_lookup(options, "wpad");
|
||||
if (str) {
|
||||
nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
|
||||
nm_l3_config_data_set_proxy_pac_url(l3cd, str);
|
||||
}
|
||||
|
||||
return g_steal_pointer(&l3cd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
ip6_add_domain_search(gpointer data, gpointer user_data)
|
||||
{
|
||||
nm_ip6_config_add_search(NM_IP6_CONFIG(user_data), (const char *) data);
|
||||
}
|
||||
|
||||
NMPlatformIP6Address
|
||||
nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options)
|
||||
{
|
||||
|
|
@ -635,25 +623,29 @@ nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options)
|
|||
return address;
|
||||
}
|
||||
|
||||
NMIP6Config *
|
||||
NML3ConfigData *
|
||||
nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
|
||||
int ifindex,
|
||||
const char * iface,
|
||||
GHashTable * options,
|
||||
gboolean info_only)
|
||||
{
|
||||
gs_unref_object NMIP6Config *ip6_config = NULL;
|
||||
struct in6_addr tmp_addr;
|
||||
NMPlatformIP6Address address;
|
||||
char * str = NULL;
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
struct in6_addr tmp_addr;
|
||||
NMPlatformIP6Address address;
|
||||
char * str = NULL;
|
||||
guint32 now;
|
||||
|
||||
g_return_val_if_fail(options != NULL, NULL);
|
||||
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.plen = 128;
|
||||
address.timestamp = nm_utils_get_monotonic_timestamp_sec();
|
||||
now = nm_utils_get_monotonic_timestamp_sec();
|
||||
|
||||
ip6_config = nm_ip6_config_new(multi_idx, ifindex);
|
||||
address = (NMPlatformIP6Address){
|
||||
.plen = 128,
|
||||
.timestamp = now,
|
||||
};
|
||||
|
||||
l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
|
||||
str = g_hash_table_lookup(options, "max_life");
|
||||
if (str) {
|
||||
|
|
@ -676,7 +668,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
address.address = tmp_addr;
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_DHCP;
|
||||
nm_ip6_config_add_address(ip6_config, &address);
|
||||
nm_l3_config_data_add_address_6(l3cd, &address);
|
||||
_LOG2I(LOGD_DHCP6, iface, " address %s", str);
|
||||
} else if (info_only == FALSE) {
|
||||
/* No address in Managed mode is a hard error */
|
||||
|
|
@ -695,7 +687,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
for (s = dns; dns && *s; s++) {
|
||||
if (inet_pton(AF_INET6, *s, &tmp_addr) > 0) {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
|
||||
nm_ip6_config_add_nameserver(ip6_config, &tmp_addr);
|
||||
nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &tmp_addr);
|
||||
_LOG2I(LOGD_DHCP6, iface, " nameserver '%s'", *s);
|
||||
}
|
||||
} else
|
||||
|
|
@ -705,9 +697,9 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
|
|||
|
||||
str = g_hash_table_lookup(options, "dhcp6_domain_search");
|
||||
if (str)
|
||||
process_domain_search(iface, str, ip6_add_domain_search, ip6_config);
|
||||
process_domain_search(AF_INET6, iface, str, l3cd);
|
||||
|
||||
return g_steal_pointer(&ip6_config);
|
||||
return g_steal_pointer(&l3cd);
|
||||
}
|
||||
|
||||
char *
|
||||
|
|
@ -838,6 +830,65 @@ nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease)
|
|||
return g_strdup_printf("%s|%s", iaid, start);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData * l3cd_old,
|
||||
const NML3ConfigData * l3cd_new,
|
||||
const NML3ConfigData **out_l3cd_merged)
|
||||
{
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd_merged = NULL;
|
||||
const NMPlatformIP6Address * addr;
|
||||
NMDhcpLease * lease_old;
|
||||
NMDhcpLease * lease_new;
|
||||
NMDedupMultiIter iter;
|
||||
const char * start;
|
||||
const char * iaid;
|
||||
|
||||
nm_assert(out_l3cd_merged);
|
||||
nm_assert(!*out_l3cd_merged);
|
||||
|
||||
if (!l3cd_old)
|
||||
return FALSE;
|
||||
if (!l3cd_new)
|
||||
return FALSE;
|
||||
|
||||
lease_new = nm_l3_config_data_get_dhcp_lease(l3cd_new, AF_INET6);
|
||||
if (!lease_new)
|
||||
return FALSE;
|
||||
|
||||
lease_old = nm_l3_config_data_get_dhcp_lease(l3cd_old, AF_INET6);
|
||||
if (!lease_old)
|
||||
return FALSE;
|
||||
|
||||
start = nm_dhcp_lease_lookup_option(lease_new, "life_starts");
|
||||
if (!start)
|
||||
return FALSE;
|
||||
iaid = nm_dhcp_lease_lookup_option(lease_new, "iaid");
|
||||
if (!iaid)
|
||||
return FALSE;
|
||||
|
||||
if (!nm_streq0(start, nm_dhcp_lease_lookup_option(lease_old, "life_starts")))
|
||||
return FALSE;
|
||||
if (!nm_streq0(iaid, nm_dhcp_lease_lookup_option(lease_old, "iaid")))
|
||||
return FALSE;
|
||||
|
||||
/* If the server sends multiple IPv6 addresses, we receive a state
|
||||
* changed event for each of them. Use the event ID to merge IPv6
|
||||
* addresses from the same transaction into a single configuration.
|
||||
**/
|
||||
|
||||
l3cd_merged = nm_l3_config_data_new_clone(l3cd_old, -1);
|
||||
|
||||
nm_l3_config_data_iter_ip6_address_for_each (&iter, l3cd_new, &addr)
|
||||
nm_l3_config_data_add_address_6(l3cd_merged, addr);
|
||||
|
||||
/* FIXME(l3cfg): Note that we keep the original NMDhcpLease. All we take from the new lease are the
|
||||
* addresses. Maybe this is not right and we should merge the leases too?? */
|
||||
nm_l3_config_data_set_dhcp_lease(l3cd_merged, AF_INET6, lease_old);
|
||||
|
||||
*out_l3cd_merged = nm_l3_config_data_ref_and_seal(g_steal_pointer(&l3cd_merged));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
|
|
|
|||
|
|
@ -8,21 +8,18 @@
|
|||
|
||||
#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,
|
||||
int ifindex,
|
||||
const char * iface,
|
||||
GHashTable * options,
|
||||
guint32 route_table,
|
||||
guint32 route_metric);
|
||||
NML3ConfigData *nm_dhcp_utils_ip4_config_from_options(struct _NMDedupMultiIndex *multi_idx,
|
||||
int ifindex,
|
||||
const char * iface,
|
||||
GHashTable * options);
|
||||
|
||||
NMIP6Config *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
|
||||
int ifindex,
|
||||
const char * iface,
|
||||
GHashTable * options,
|
||||
gboolean info_only);
|
||||
NML3ConfigData *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
|
||||
int ifindex,
|
||||
const char * iface,
|
||||
GHashTable * options,
|
||||
gboolean info_only);
|
||||
|
||||
NMPlatformIP6Address nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options);
|
||||
|
||||
|
|
@ -38,6 +35,10 @@ gboolean nm_dhcp_utils_get_leasefile_path(int addr_family,
|
|||
|
||||
char *nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease);
|
||||
|
||||
gboolean nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData * l3cd_old,
|
||||
const NML3ConfigData * l3cd_new,
|
||||
const NML3ConfigData **out_l3cd_merged);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline gboolean
|
||||
|
|
|
|||
|
|
@ -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,58 +72,57 @@ static const Option generic_options[] = {
|
|||
static void
|
||||
test_generic_options(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const NMPlatformIP4Address * address;
|
||||
const NMPlatformIP4Route * route;
|
||||
guint32 tmp;
|
||||
const char * expected_addr = "192.168.1.106";
|
||||
const char * expected_gw = "192.168.1.1";
|
||||
const char * expected_dns1 = "216.254.95.2";
|
||||
const char * expected_dns2 = "216.231.41.2";
|
||||
const char * expected_search1 = "foobar.com";
|
||||
const char * expected_search2 = "blah.foobar.com";
|
||||
const char * expected_route1_dest = "10.1.1.5";
|
||||
const char * expected_route1_gw = "10.1.1.1";
|
||||
const char * expected_route2_dest = "100.99.88.56";
|
||||
const char * expected_route2_gw = "10.1.1.1";
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const NMPlatformIP4Address * address;
|
||||
const NMPlatformIP4Route * route;
|
||||
guint32 tmp;
|
||||
const char * expected_addr = "192.168.1.106";
|
||||
const char * expected_gw = "192.168.1.1";
|
||||
const char * expected_dns1 = "216.254.95.2";
|
||||
const char * expected_dns2 = "216.231.41.2";
|
||||
const char * expected_search1 = "foobar.com";
|
||||
const char * expected_search2 = "blah.foobar.com";
|
||||
const char * expected_route1_dest = "10.1.1.5";
|
||||
const char * expected_route1_gw = "10.1.1.1";
|
||||
const char * expected_route2_dest = "100.99.88.56";
|
||||
const char * expected_route2_gw = "10.1.1.1";
|
||||
const char *const * strarr;
|
||||
const in_addr_t * ia_arr;
|
||||
guint u;
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
options = fill_table(generic_options, NULL);
|
||||
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;
|
||||
const NMPlatformIP4Address * address;
|
||||
guint32 tmp;
|
||||
const char * expected_wins1 = "63.12.199.5";
|
||||
const char * expected_wins2 = "150.4.88.120";
|
||||
static const Option data[] = {{"netbios_name_servers", "63.12.199.5 150.4.88.120"},
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const NMPlatformIP4Address * address;
|
||||
const char * expected_wins1 = "63.12.199.5";
|
||||
const char * expected_wins2 = "150.4.88.120";
|
||||
static const Option data[] = {{"netbios_name_servers", "63.12.199.5 150.4.88.120"},
|
||||
{NULL, NULL}};
|
||||
const in_addr_t * ia_arr;
|
||||
guint u;
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
|
||||
/* IP4 address */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
|
||||
address = _nmtst_ip4_config_get_address(ip4_config, 0);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
|
||||
address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
|
||||
g_assert(address);
|
||||
g_assert_cmpint(nm_ip4_config_get_num_wins(ip4_config), ==, 2);
|
||||
g_assert(inet_pton(AF_INET, expected_wins1, &tmp) > 0);
|
||||
g_assert(nm_ip4_config_get_wins(ip4_config, 0) == tmp);
|
||||
g_assert(inet_pton(AF_INET, expected_wins2, &tmp) > 0);
|
||||
g_assert(nm_ip4_config_get_wins(ip4_config, 1) == tmp);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
ia_arr = nm_l3_config_data_get_wins(l3cd, &u);
|
||||
g_assert_cmpint(u, ==, 2);
|
||||
nmtst_assert_ip4_address(ia_arr[0], expected_wins1);
|
||||
nmtst_assert_ip4_address(ia_arr[1], expected_wins2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_vendor_option_metered(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
static const Option data[] = {{"vendor_encapsulated_options", "ANDROID_METERED"}, {NULL, NULL}};
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
g_assert(nm_ip4_config_get_metered(ip4_config) == FALSE);
|
||||
g_hash_table_destroy(options);
|
||||
g_clear_object(&ip4_config);
|
||||
options = fill_table(generic_options, NULL);
|
||||
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);
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
g_assert(nm_l3_config_data_get_metered(l3cd) == TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -252,18 +243,18 @@ test_parse_search_list(void)
|
|||
}
|
||||
|
||||
static void
|
||||
ip4_test_route(NMIP4Config *ip4_config,
|
||||
guint route_num,
|
||||
const char * expected_dest,
|
||||
const char * expected_gw,
|
||||
guint expected_prefix)
|
||||
ip4_test_route(const NML3ConfigData *l3cd,
|
||||
guint route_num,
|
||||
const char * expected_dest,
|
||||
const char * expected_gw,
|
||||
guint expected_prefix)
|
||||
{
|
||||
const NMPlatformIP4Route *route;
|
||||
guint32 tmp;
|
||||
|
||||
g_assert(expected_prefix <= 32);
|
||||
|
||||
route = _nmtst_ip4_config_get_route(ip4_config, route_num);
|
||||
route = nmtst_l3_config_data_get_route_at_4(l3cd, route_num);
|
||||
g_assert(inet_pton(AF_INET, expected_dest, &tmp) > 0);
|
||||
g_assert(route->network == tmp);
|
||||
g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
|
||||
|
|
@ -272,110 +263,105 @@ ip4_test_route(NMIP4Config *ip4_config,
|
|||
g_assert_cmpint(route->metric, ==, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ip4_test_gateway(NMIP4Config *ip4_config, const char *expected_gw)
|
||||
{
|
||||
guint32 tmp;
|
||||
|
||||
g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
|
||||
g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
|
||||
g_assert(nmtst_ip4_config_get_gateway(ip4_config) == tmp);
|
||||
}
|
||||
#define ip4_test_gateway(l3cd, expected_gw) \
|
||||
G_STMT_START \
|
||||
{ \
|
||||
const NML3ConfigData *_l3cd = (l3cd); \
|
||||
\
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_addresses(_l3cd, AF_INET), ==, 1); \
|
||||
nmtst_assert_ip_address(AF_INET, \
|
||||
nmtst_l3_config_data_get_best_gateway(_l3cd, AF_INET), \
|
||||
expected_gw); \
|
||||
} \
|
||||
G_STMT_END
|
||||
|
||||
static void
|
||||
test_classless_static_routes_1(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
const char * expected_route2_dest = "10.0.0.0";
|
||||
const char * expected_route2_gw = "10.17.66.41";
|
||||
static const Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
const char * expected_route2_dest = "10.0.0.0";
|
||||
const char * expected_route2_gw = "10.17.66.41";
|
||||
static const Option data[] = {
|
||||
/* dhclient custom format */
|
||||
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 8 10 10 17 66 41"},
|
||||
{NULL, NULL}};
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
|
||||
/* IP4 routes */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
|
||||
ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
|
||||
ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 8);
|
||||
ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_classless_static_routes_2(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
const char * expected_route2_dest = "10.0.0.0";
|
||||
const char * expected_route2_gw = "10.17.66.41";
|
||||
static const Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
const char * expected_route2_dest = "10.0.0.0";
|
||||
const char * expected_route2_gw = "10.17.66.41";
|
||||
static const Option data[] = {
|
||||
/* dhcpcd format */
|
||||
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41"},
|
||||
{NULL, NULL}};
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
|
||||
/* IP4 routes */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
|
||||
ip4_test_route(ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
|
||||
ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 8);
|
||||
ip4_test_route(l3cd, 2, "0.0.0.0", expected_route1_gw, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_fedora_dhclient_classless_static_routes(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "129.210.177.128";
|
||||
const char * expected_route1_gw = "192.168.0.113";
|
||||
const char * expected_route2_dest = "2.0.0.0";
|
||||
const char * expected_route2_gw = "10.34.255.6";
|
||||
const char * expected_gateway = "192.168.0.113";
|
||||
static const Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "129.210.177.128";
|
||||
const char * expected_route1_gw = "192.168.0.113";
|
||||
const char * expected_route2_dest = "2.0.0.0";
|
||||
const char * expected_route2_gw = "10.34.255.6";
|
||||
const char * expected_gateway = "192.168.0.113";
|
||||
static const Option data[] = {
|
||||
/* Fedora dhclient format */
|
||||
{"classless_static_routes",
|
||||
"0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6"},
|
||||
{NULL, NULL}};
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
|
||||
/* IP4 routes */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 25);
|
||||
ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 7);
|
||||
ip4_test_route(ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
|
||||
ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 25);
|
||||
ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 7);
|
||||
ip4_test_route(l3cd, 2, "0.0.0.0", expected_route1_gw, 0);
|
||||
|
||||
/* Gateway */
|
||||
ip4_test_gateway(ip4_config, expected_gateway);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
ip4_test_gateway(l3cd, expected_gateway);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dhclient_invalid_classless_routes_1(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
static const Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
static const Option data[] = {
|
||||
/* dhclient format */
|
||||
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 45 10 17 66 41"},
|
||||
{NULL, NULL}};
|
||||
|
|
@ -384,27 +370,25 @@ test_dhclient_invalid_classless_routes_1(void)
|
|||
options = fill_table(data, options);
|
||||
|
||||
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
g_test_assert_expected_messages();
|
||||
|
||||
/* IP4 routes */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
|
||||
ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dhcpcd_invalid_classless_routes_1(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "10.1.1.5";
|
||||
const char * expected_route1_gw = "10.1.1.1";
|
||||
const char * expected_route2_dest = "100.99.88.56";
|
||||
const char * expected_route2_gw = "10.1.1.1";
|
||||
static const Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "10.1.1.5";
|
||||
const char * expected_route1_gw = "10.1.1.1";
|
||||
const char * expected_route2_dest = "100.99.88.56";
|
||||
const char * expected_route2_gw = "10.1.1.1";
|
||||
static const Option data[] = {
|
||||
/* dhcpcd format */
|
||||
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.adfadf/44 10.17.66.41"},
|
||||
{NULL, NULL}};
|
||||
|
|
@ -413,30 +397,28 @@ test_dhcpcd_invalid_classless_routes_1(void)
|
|||
options = fill_table(data, options);
|
||||
|
||||
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
g_test_assert_expected_messages();
|
||||
|
||||
/* Test falling back to old-style static routes if the classless static
|
||||
* routes are invalid.
|
||||
*/
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
|
||||
ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
|
||||
ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
|
||||
ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
|
||||
ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
|
||||
ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dhclient_invalid_classless_routes_2(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "10.1.1.5";
|
||||
const char * expected_route1_gw = "10.1.1.1";
|
||||
const char * expected_route2_dest = "100.99.88.56";
|
||||
const char * expected_route2_gw = "10.1.1.1";
|
||||
static const Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "10.1.1.5";
|
||||
const char * expected_route1_gw = "10.1.1.1";
|
||||
const char * expected_route2_dest = "100.99.88.56";
|
||||
const char * expected_route2_gw = "10.1.1.1";
|
||||
static const Option data[] = {
|
||||
{"rfc3442_classless_static_routes", "45 10 17 66 41 24 192 168 10 192 168 1 1"},
|
||||
{NULL, NULL}};
|
||||
|
||||
|
|
@ -444,30 +426,28 @@ test_dhclient_invalid_classless_routes_2(void)
|
|||
options = fill_table(data, options);
|
||||
|
||||
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
g_test_assert_expected_messages();
|
||||
|
||||
/* Test falling back to old-style static routes if the classless static
|
||||
* routes are invalid.
|
||||
*/
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
|
||||
ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
|
||||
ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
|
||||
ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
|
||||
ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
|
||||
ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dhcpcd_invalid_classless_routes_2(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "10.1.1.5";
|
||||
const char * expected_route1_gw = "10.1.1.1";
|
||||
const char * expected_route2_dest = "100.99.88.56";
|
||||
const char * expected_route2_gw = "10.1.1.1";
|
||||
static const Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "10.1.1.5";
|
||||
const char * expected_route1_gw = "10.1.1.1";
|
||||
const char * expected_route2_dest = "100.99.88.56";
|
||||
const char * expected_route2_gw = "10.1.1.1";
|
||||
static const Option data[] = {
|
||||
{"classless_static_routes", "10.0.adfadf/44 10.17.66.41 192.168.10.0/24 192.168.1.1"},
|
||||
{NULL, NULL}};
|
||||
|
||||
|
|
@ -475,7 +455,7 @@ test_dhcpcd_invalid_classless_routes_2(void)
|
|||
options = fill_table(data, options);
|
||||
|
||||
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
g_test_assert_expected_messages();
|
||||
|
||||
/* Test falling back to old-style static routes if the classless static
|
||||
|
|
@ -483,22 +463,20 @@ test_dhcpcd_invalid_classless_routes_2(void)
|
|||
*/
|
||||
|
||||
/* Routes */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
|
||||
ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
|
||||
ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
|
||||
ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
|
||||
ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
|
||||
ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dhclient_invalid_classless_routes_3(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
static const Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
static const Option data[] = {
|
||||
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 32 128 10 17 66 41"},
|
||||
{NULL, NULL}};
|
||||
|
||||
|
|
@ -506,25 +484,23 @@ test_dhclient_invalid_classless_routes_3(void)
|
|||
options = fill_table(data, options);
|
||||
|
||||
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
g_test_assert_expected_messages();
|
||||
|
||||
/* IP4 routes */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
|
||||
ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dhcpcd_invalid_classless_routes_3(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
static Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
static Option data[] = {
|
||||
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 128/32 10.17.66.41"},
|
||||
{NULL, NULL}};
|
||||
|
||||
|
|
@ -532,133 +508,124 @@ test_dhcpcd_invalid_classless_routes_3(void)
|
|||
options = fill_table(data, options);
|
||||
|
||||
NMTST_EXPECT_NM_WARN("*DHCP provided invalid classless static route*");
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
g_test_assert_expected_messages();
|
||||
|
||||
/* IP4 routes */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
|
||||
ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dhclient_gw_in_classless_routes(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
const char * expected_gateway = "192.2.3.4";
|
||||
static Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
const char * expected_gateway = "192.2.3.4";
|
||||
static Option data[] = {
|
||||
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 0 192 2 3 4"},
|
||||
{NULL, NULL}};
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
|
||||
/* IP4 routes */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
|
||||
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;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
const char * expected_gateway = "192.2.3.4";
|
||||
static Option data[] = {
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_route1_dest = "192.168.10.0";
|
||||
const char * expected_route1_gw = "192.168.1.1";
|
||||
const char * expected_gateway = "192.2.3.4";
|
||||
static Option data[] = {
|
||||
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 0.0.0.0/0 192.2.3.4"},
|
||||
{NULL, NULL}};
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
|
||||
/* IP4 routes */
|
||||
g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
|
||||
ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
|
||||
ip4_test_route(ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
|
||||
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;
|
||||
const char * expected_search0 = "host1";
|
||||
const char * expected_search1 = "host2";
|
||||
const char * expected_search2 = "host3";
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const char * expected_search0 = "host1";
|
||||
const char * expected_search1 = "host2";
|
||||
const char * expected_search2 = "host3";
|
||||
static const Option data[] = {{"domain_search", "host1\\032host2\\032host3"}, {NULL, NULL}};
|
||||
const char *const * strarr;
|
||||
guint u;
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
options = fill_table(generic_options, NULL);
|
||||
options = fill_table(data, options);
|
||||
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;
|
||||
const NMPlatformIP4Address * address;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const NMPlatformIP4Address * address;
|
||||
|
||||
options = fill_table(generic_options, NULL);
|
||||
g_hash_table_insert(options, "ip_address", (gpointer) ip);
|
||||
g_hash_table_remove(options, "subnet_mask");
|
||||
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
|
||||
g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
|
||||
address = _nmtst_ip4_config_get_address(ip4_config, 0);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
|
||||
address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
|
||||
g_assert(address);
|
||||
g_assert_cmpint(address->plen, ==, expected_prefix);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -682,9 +649,9 @@ test_ip4_missing_prefix_8(void)
|
|||
static void
|
||||
test_ip4_prefix_classless(void)
|
||||
{
|
||||
GHashTable * options;
|
||||
gs_unref_object NMIP4Config *ip4_config = NULL;
|
||||
const NMPlatformIP4Address * address;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
|
||||
const NMPlatformIP4Address * address;
|
||||
|
||||
/* Ensure that the missing-subnet-mask handler doesn't mangle classless
|
||||
* subnet masks at all. The handler should trigger only if the server
|
||||
|
|
@ -695,14 +662,12 @@ test_ip4_prefix_classless(void)
|
|||
g_hash_table_insert(options, "ip_address", "172.16.54.22");
|
||||
g_hash_table_insert(options, "subnet_mask", "255.255.252.0");
|
||||
|
||||
ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
|
||||
l3cd = _ip4_config_from_options(1, "eth0", options);
|
||||
|
||||
g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
|
||||
address = _nmtst_ip4_config_get_address(ip4_config, 0);
|
||||
g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
|
||||
address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
|
||||
g_assert(address);
|
||||
g_assert_cmpint(address->plen, ==, 22);
|
||||
|
||||
g_hash_table_destroy(options);
|
||||
}
|
||||
|
||||
#define COMPARE_ID(src, is_str, expected, expected_len) \
|
||||
|
|
|
|||
|
|
@ -19,10 +19,9 @@
|
|||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "libnm-platform/nm-platform.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-ip4-config.h"
|
||||
#include "nm-ip6-config.h"
|
||||
#include "nm-dbus-manager.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-l3-config-data.h"
|
||||
|
||||
#define PIDFILE NMRUNDIR "/dnsmasq.pid"
|
||||
#define CONFDIR NMCONFDIR "/dnsmasq.d"
|
||||
|
|
@ -806,20 +805,22 @@ add_global_config(NMDnsDnsmasq * self,
|
|||
static void
|
||||
add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsConfigIPData *ip_data)
|
||||
{
|
||||
NMIPConfig * ip_config = ip_data->ip_config;
|
||||
gconstpointer addr;
|
||||
const char * iface, *domain;
|
||||
const char * iface;
|
||||
const char * domain;
|
||||
char ip_addr_to_string_buf[IP_ADDR_TO_STRING_BUFLEN];
|
||||
int addr_family;
|
||||
guint i, j, num;
|
||||
gconstpointer nameservers;
|
||||
guint num;
|
||||
guint i;
|
||||
guint j;
|
||||
|
||||
iface = nm_platform_link_get_name(NM_PLATFORM_GET, ip_data->data->ifindex);
|
||||
addr_family = nm_ip_config_get_addr_family(ip_config);
|
||||
iface = nm_platform_link_get_name(NM_PLATFORM_GET, ip_data->data->ifindex);
|
||||
|
||||
num = nm_ip_config_get_num_nameservers(ip_config);
|
||||
nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
|
||||
for (i = 0; i < num; i++) {
|
||||
addr = nm_ip_config_get_nameserver(ip_config, i);
|
||||
ip_addr_to_string(addr_family, addr, iface, ip_addr_to_string_buf);
|
||||
gconstpointer addr;
|
||||
|
||||
addr = nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i);
|
||||
ip_addr_to_string(ip_data->addr_family, addr, iface, ip_addr_to_string_buf);
|
||||
|
||||
if (!ip_data->domains.has_default_route_explicit && ip_data->domains.has_default_route)
|
||||
add_dnsmasq_nameserver(self, servers, ip_addr_to_string_buf, NULL);
|
||||
|
|
@ -846,7 +847,7 @@ add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsConfigIPD
|
|||
static GVariant *
|
||||
create_update_args(NMDnsDnsmasq * self,
|
||||
const NMGlobalDnsConfig *global_config,
|
||||
const CList * ip_config_lst_head,
|
||||
const CList * ip_data_lst_head,
|
||||
const char * hostname)
|
||||
{
|
||||
GVariantBuilder servers;
|
||||
|
|
@ -857,7 +858,7 @@ create_update_args(NMDnsDnsmasq * self,
|
|||
if (global_config)
|
||||
add_global_config(self, &servers, global_config);
|
||||
else {
|
||||
c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst)
|
||||
c_list_for_each_entry (ip_data, ip_data_lst_head, ip_data_lst)
|
||||
add_ip_config(self, &servers, ip_data);
|
||||
}
|
||||
|
||||
|
|
@ -1122,7 +1123,7 @@ start_dnsmasq(NMDnsDnsmasq *self, gboolean force_start, GError **error)
|
|||
static gboolean
|
||||
update(NMDnsPlugin * plugin,
|
||||
const NMGlobalDnsConfig *global_config,
|
||||
const CList * ip_config_lst_head,
|
||||
const CList * ip_data_lst_head,
|
||||
const char * hostname,
|
||||
GError ** error)
|
||||
{
|
||||
|
|
@ -1134,7 +1135,7 @@ update(NMDnsPlugin * plugin,
|
|||
|
||||
nm_clear_pointer(&priv->set_server_ex_args, g_variant_unref);
|
||||
priv->set_server_ex_args =
|
||||
g_variant_ref_sink(create_update_args(self, global_config, ip_config_lst_head, hostname));
|
||||
g_variant_ref_sink(create_update_args(self, global_config, ip_data_lst_head, hostname));
|
||||
|
||||
send_dnsmasq_update(self);
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -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,21 @@
|
|||
#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-ip-config.h"
|
||||
#include "nm-l3-config-data.h"
|
||||
#include "nm-manager.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
#define HASH_LEN NM_UTILS_CHECKSUM_LENGTH_SHA1
|
||||
|
||||
|
|
@ -84,16 +85,18 @@ 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;
|
||||
|
||||
|
|
@ -159,11 +162,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 +206,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 +237,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 +259,36 @@ _ASSERT_dns_config_ip_data(const NMDnsConfigIPData *ip_data)
|
|||
if (ip_data->domains.has_default_route_exclusive)
|
||||
nm_assert(ip_data->domains.has_default_route);
|
||||
}
|
||||
nm_assert(_dns_config_ip_data_get_dns_priority(ip_data) != 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static NMDnsConfigIPData *
|
||||
_dns_config_ip_data_new(NMDnsConfigData * data,
|
||||
NMIPConfig * ip_config,
|
||||
NMDnsIPConfigType ip_config_type)
|
||||
_dns_config_ip_data_new(NMDnsConfigData * data,
|
||||
int addr_family,
|
||||
gconstpointer source_tag,
|
||||
const NML3ConfigData *l3cd,
|
||||
NMDnsIPConfigType ip_config_type)
|
||||
{
|
||||
NMDnsConfigIPData *ip_data;
|
||||
|
||||
_ASSERT_dns_config_data(data);
|
||||
nm_assert(NM_IS_IP_CONFIG(ip_config));
|
||||
nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
|
||||
nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED);
|
||||
|
||||
ip_data = g_slice_new(NMDnsConfigIPData);
|
||||
*ip_data = (NMDnsConfigIPData){
|
||||
.data = data,
|
||||
.ip_config = g_object_ref(ip_config),
|
||||
.source_tag = source_tag,
|
||||
.l3cd = nm_l3_config_data_ref_and_seal(l3cd),
|
||||
.ip_config_type = ip_config_type,
|
||||
.addr_family = addr_family,
|
||||
};
|
||||
c_list_link_tail(&data->data_lst_head, &ip_data->data_lst);
|
||||
c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_config_lst_head,
|
||||
&ip_data->ip_config_lst);
|
||||
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 +300,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 +320,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 +335,16 @@ _mgr_get_ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *u
|
|||
}
|
||||
|
||||
static CList *
|
||||
_mgr_get_ip_config_lst_head(NMDnsManager *self)
|
||||
_mgr_get_ip_data_lst_head(NMDnsManager *self)
|
||||
{
|
||||
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
if (G_UNLIKELY(priv->ip_config_lst_need_sort)) {
|
||||
priv->ip_config_lst_need_sort = FALSE;
|
||||
c_list_sort(&priv->ip_config_lst_head, _mgr_get_ip_config_lst_cmp, NULL);
|
||||
if (G_UNLIKELY(priv->ip_data_lst_need_sort)) {
|
||||
priv->ip_data_lst_need_sort = FALSE;
|
||||
c_list_sort(&priv->ip_data_lst_head, _mgr_get_ip_data_lst_cmp, NULL);
|
||||
}
|
||||
|
||||
return &priv->ip_config_lst_head;
|
||||
return &priv->ip_data_lst_head;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -430,28 +424,33 @@ add_dns_option_item(GPtrArray *array, const char *str)
|
|||
}
|
||||
|
||||
static void
|
||||
add_dns_domains(GPtrArray * array,
|
||||
const NMIPConfig *ip_config,
|
||||
gboolean include_routing,
|
||||
gboolean dup)
|
||||
add_dns_domains(GPtrArray * array,
|
||||
int addr_family,
|
||||
const NML3ConfigData *l3cd,
|
||||
gboolean include_routing,
|
||||
gboolean dup)
|
||||
{
|
||||
guint num_domains, num_searches, i;
|
||||
const char *str;
|
||||
const char *const *domains;
|
||||
const char *const *searches;
|
||||
guint num_domains;
|
||||
guint num_searches;
|
||||
guint i;
|
||||
const char * str;
|
||||
|
||||
num_domains = nm_ip_config_get_num_domains(ip_config);
|
||||
num_searches = nm_ip_config_get_num_searches(ip_config);
|
||||
domains = nm_l3_config_data_get_domains(l3cd, addr_family, &num_domains);
|
||||
searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches);
|
||||
|
||||
for (i = 0; i < num_searches; i++) {
|
||||
str = nm_ip_config_get_search(ip_config, i);
|
||||
str = searches[i];
|
||||
if (!include_routing && domain_is_routing(str))
|
||||
continue;
|
||||
if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE))
|
||||
continue;
|
||||
add_string_item(array, str, dup);
|
||||
}
|
||||
if (num_domains > 1 || !num_searches) {
|
||||
if (num_domains > 1 || num_searches == 0) {
|
||||
for (i = 0; i < num_domains; i++) {
|
||||
str = nm_ip_config_get_domain(ip_config, i);
|
||||
str = domains[i];
|
||||
if (!include_routing && domain_is_routing(str))
|
||||
continue;
|
||||
if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE))
|
||||
|
|
@ -462,26 +461,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;
|
||||
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 +499,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 +525,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1122,9 +1117,9 @@ compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[
|
|||
|
||||
/* 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);
|
||||
head = _mgr_get_ip_data_lst_head(self);
|
||||
c_list_for_each_entry (ip_data, head, ip_data_lst)
|
||||
nm_ip_config_dns_hash(ip_data->l3cd, sum, ip_data->addr_family);
|
||||
}
|
||||
|
||||
nm_utils_checksum_get_digest_len(sum, buffer, HASH_LEN);
|
||||
|
|
@ -1172,19 +1167,21 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf)
|
|||
}
|
||||
|
||||
static const char *
|
||||
get_nameserver_list(const NMIPConfig *config, NMStrBuf *tmp_strbuf)
|
||||
get_nameserver_list(int addr_family, const NML3ConfigData *l3cd, NMStrBuf *tmp_strbuf)
|
||||
{
|
||||
char buf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
int addr_family;
|
||||
guint num;
|
||||
guint i;
|
||||
char buf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
guint num;
|
||||
guint i;
|
||||
gconstpointer nameservers;
|
||||
|
||||
nm_str_buf_reset(tmp_strbuf);
|
||||
|
||||
addr_family = nm_ip_config_get_addr_family(config);
|
||||
num = nm_ip_config_get_num_nameservers(config);
|
||||
nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num);
|
||||
for (i = 0; i < num; i++) {
|
||||
nm_utils_inet_ntop(addr_family, nm_ip_config_get_nameserver(config, i), buf);
|
||||
const NMIPAddr *addr;
|
||||
|
||||
addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i);
|
||||
nm_utils_inet_ntop(addr_family, addr->addr_ptr, buf);
|
||||
if (i > 0)
|
||||
nm_str_buf_append_c(tmp_strbuf, ' ');
|
||||
nm_str_buf_append(tmp_strbuf, buf);
|
||||
|
|
@ -1227,36 +1224,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 +1292,32 @@ _collect_resolv_conf_data(NMDnsManager * self,
|
|||
/*****************************************************************************/
|
||||
|
||||
static char **
|
||||
get_ip_rdns_domains(NMIPConfig *ip_config)
|
||||
get_ip_rdns_domains(int addr_family, const NML3ConfigData *l3cd)
|
||||
{
|
||||
int addr_family = nm_ip_config_get_addr_family(ip_config);
|
||||
char ** strv;
|
||||
GPtrArray * domains;
|
||||
NMDedupMultiIter ipconf_iter;
|
||||
const NMPlatformIPAddress *address;
|
||||
const NMPlatformIPRoute * route;
|
||||
|
||||
nm_assert_addr_family(addr_family);
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
char ** strv;
|
||||
GPtrArray * domains;
|
||||
NMDedupMultiIter ipconf_iter;
|
||||
const NMPObject *obj;
|
||||
|
||||
domains = g_ptr_array_sized_new(5);
|
||||
|
||||
nm_ip_config_iter_ip_address_for_each (&ipconf_iter, ip_config, &address) {
|
||||
nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
|
||||
l3cd,
|
||||
&obj,
|
||||
NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) {
|
||||
nm_utils_get_reverse_dns_domains_ip(addr_family,
|
||||
address->address_ptr,
|
||||
address->plen,
|
||||
NMP_OBJECT_CAST_IP_ADDRESS(obj)->address_ptr,
|
||||
NMP_OBJECT_CAST_IP_ADDRESS(obj)->plen,
|
||||
domains);
|
||||
}
|
||||
|
||||
nm_ip_config_iter_ip_route_for_each (&ipconf_iter, ip_config, &route) {
|
||||
nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
|
||||
l3cd,
|
||||
&obj,
|
||||
NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) {
|
||||
const NMPlatformIPRoute *route = NMP_OBJECT_CAST_IP_ROUTE(obj);
|
||||
|
||||
if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) {
|
||||
nm_utils_get_reverse_dns_domains_ip(addr_family,
|
||||
route->network_ptr,
|
||||
|
|
@ -1394,12 +1399,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 +1413,17 @@ _mgr_configs_data_construct(NMDnsManager *self)
|
|||
}
|
||||
#endif
|
||||
|
||||
c_list_for_each_entry (ip_data, head, ip_config_lst) {
|
||||
NMIPConfig *ip_config = ip_data->ip_config;
|
||||
gboolean add_wildcard = FALSE;
|
||||
c_list_for_each_entry (ip_data, head, ip_data_lst) {
|
||||
gboolean add_wildcard = FALSE;
|
||||
guint num;
|
||||
|
||||
if (!nm_ip_config_get_num_nameservers(ip_config))
|
||||
nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
|
||||
if (num == 0)
|
||||
continue;
|
||||
if (nm_ip_config_best_default_route_get(ip_config))
|
||||
if (nm_l3_config_data_get_best_default_route(ip_data->l3cd, ip_data->addr_family)) {
|
||||
/* FIXME(l3cfg): the best-default route of a l3cd is not significant! */
|
||||
add_wildcard = TRUE;
|
||||
else {
|
||||
} else {
|
||||
/* If a VPN has never-default=no but doesn't get a default
|
||||
* route (this can happen for example when the server
|
||||
* pushes routes with openconnect), and there are no
|
||||
|
|
@ -1424,9 +1431,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, &num)
|
||||
&& !nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, &num))
|
||||
add_wildcard = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1437,29 +1445,33 @@ _mgr_configs_data_construct(NMDnsManager *self)
|
|||
}
|
||||
}
|
||||
|
||||
c_list_for_each_entry (ip_data, head, ip_config_lst) {
|
||||
NMIPConfig * ip_config = ip_data->ip_config;
|
||||
int priority;
|
||||
const char **domains;
|
||||
guint n_searches;
|
||||
guint n_domains;
|
||||
guint num_dom1;
|
||||
guint num_dom2;
|
||||
guint n_domains_allocated;
|
||||
guint i;
|
||||
gboolean has_default_route_maybe = FALSE;
|
||||
gboolean has_default_route_explicit = FALSE;
|
||||
gboolean has_default_route_auto = FALSE;
|
||||
c_list_for_each_entry (ip_data, head, ip_data_lst) {
|
||||
int priority;
|
||||
const char ** domains;
|
||||
const char *const *strv_searches;
|
||||
const char *const *strv_domains;
|
||||
guint n_searches;
|
||||
guint n_domains;
|
||||
guint num_dom1;
|
||||
guint num_dom2;
|
||||
guint n_domains_allocated;
|
||||
guint i;
|
||||
gboolean has_default_route_maybe = FALSE;
|
||||
gboolean has_default_route_explicit = FALSE;
|
||||
gboolean has_default_route_auto = FALSE;
|
||||
guint num;
|
||||
|
||||
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 +1499,10 @@ _mgr_configs_data_construct(NMDnsManager *self)
|
|||
/* searches are preferred over domains */
|
||||
if (n_searches > 0) {
|
||||
for (i = 0; i < n_searches; i++)
|
||||
domains[num_dom1++] = nm_ip_config_get_search(ip_config, i);
|
||||
domains[num_dom1++] = strv_searches[i];
|
||||
} else {
|
||||
for (i = 0; i < n_domains; i++)
|
||||
domains[num_dom1++] = nm_ip_config_get_domain(ip_config, i);
|
||||
domains[num_dom1++] = strv_domains[i];
|
||||
}
|
||||
|
||||
nm_assert(num_dom1 < n_domains_allocated);
|
||||
|
|
@ -1578,8 +1590,8 @@ _mgr_configs_data_construct(NMDnsManager *self)
|
|||
|
||||
nm_assert(!ip_data->domains.search);
|
||||
nm_assert(!ip_data->domains.reverse);
|
||||
ip_data->domains.search = domains;
|
||||
ip_data->domains.reverse = get_ip_rdns_domains(ip_config);
|
||||
ip_data->domains.search = domains;
|
||||
ip_data->domains.reverse = get_ip_rdns_domains(ip_data->addr_family, ip_data->l3cd);
|
||||
ip_data->domains.has_default_route_explicit = has_default_route_explicit;
|
||||
ip_data->domains.has_default_route_exclusive =
|
||||
has_default_route_explicit || (priority < 0 && has_default_route_auto);
|
||||
|
|
@ -1611,8 +1623,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 +1655,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;
|
||||
|
|
@ -1680,7 +1694,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 +1716,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 +1848,101 @@ plugin_skip:;
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigIPData *ip_data)
|
||||
{
|
||||
_ASSERT_dns_config_ip_data(ip_data);
|
||||
|
||||
NM_DNS_MANAGER_GET_PRIVATE(ip_data->data->self)->ip_config_lst_need_sort = TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dns_manager_set_ip_config(NMDnsManager * self,
|
||||
NMIPConfig * ip_config,
|
||||
NMDnsIPConfigType ip_config_type)
|
||||
nm_dns_manager_set_ip_config(NMDnsManager * self,
|
||||
int addr_family,
|
||||
gconstpointer source_tag,
|
||||
const NML3ConfigData *l3cd,
|
||||
NMDnsIPConfigType ip_config_type,
|
||||
gboolean replace_all)
|
||||
{
|
||||
NMDnsManagerPrivate *priv;
|
||||
NMDnsConfigIPData * ip_data;
|
||||
NMDnsConfigData * data;
|
||||
int ifindex;
|
||||
gboolean changed = FALSE;
|
||||
NMDnsConfigIPData * ip_data = NULL;
|
||||
int dns_priority;
|
||||
|
||||
g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE);
|
||||
g_return_val_if_fail(NM_IS_IP_CONFIG(ip_config), FALSE);
|
||||
g_return_val_if_fail(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd), FALSE);
|
||||
g_return_val_if_fail(source_tag, FALSE);
|
||||
|
||||
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 = 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;
|
||||
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) {
|
||||
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 +1957,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,6 +2034,7 @@ 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 */
|
||||
|
|
@ -1973,7 +2051,6 @@ 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);
|
||||
|
|
@ -1982,11 +2059,11 @@ nm_dns_manager_end_updates(NMDnsManager *self, const char *func)
|
|||
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");
|
||||
priv->config_changed = (memcmp(new, priv->prev_hash, sizeof(new)) != 0) ? TRUE : FALSE;
|
||||
_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 +2072,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 +2394,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 +2415,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 +2493,54 @@ _get_config_variant(NMDnsManager *self)
|
|||
|
||||
g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
|
||||
|
||||
head = _mgr_get_ip_config_lst_head(self);
|
||||
c_list_for_each_entry (ip_data, head, ip_config_lst) {
|
||||
const NMIPConfig *ip_config = ip_data->ip_config;
|
||||
GVariantBuilder entry_builder;
|
||||
GVariantBuilder strv_builder;
|
||||
guint i, num;
|
||||
const int addr_family = nm_ip_config_get_addr_family(ip_config);
|
||||
char buf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
const NMIPAddr * addr;
|
||||
const char * ifname;
|
||||
head = _mgr_get_ip_data_lst_head(self);
|
||||
c_list_for_each_entry (ip_data, head, ip_data_lst) {
|
||||
GVariantBuilder entry_builder;
|
||||
GVariantBuilder strv_builder;
|
||||
guint num;
|
||||
guint num_domains;
|
||||
guint num_searches;
|
||||
guint i;
|
||||
char buf[NM_UTILS_INET_ADDRSTRLEN];
|
||||
const char * ifname;
|
||||
gconstpointer nameservers;
|
||||
|
||||
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 +2555,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 +2602,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 +2612,7 @@ 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 +2638,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;
|
||||
|
|
@ -97,9 +98,12 @@ NMDnsManager *nm_dns_manager_get(void);
|
|||
void nm_dns_manager_begin_updates(NMDnsManager *self, const char *func);
|
||||
void nm_dns_manager_end_updates(NMDnsManager *self, const char *func);
|
||||
|
||||
gboolean nm_dns_manager_set_ip_config(NMDnsManager * self,
|
||||
NMIPConfig * ip_config,
|
||||
NMDnsIPConfigType ip_config_type);
|
||||
gboolean nm_dns_manager_set_ip_config(NMDnsManager * self,
|
||||
int addr_family,
|
||||
gconstpointer source_tag,
|
||||
const NML3ConfigData *l3cd,
|
||||
NMDnsIPConfigType ip_config_type,
|
||||
gboolean replace_all);
|
||||
|
||||
void nm_dns_manager_set_initial_hostname(NMDnsManager *self, const char *hostname);
|
||||
void nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean skip_update);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
gboolean is_routing;
|
||||
const char *domain;
|
||||
gboolean has_config = FALSE;
|
||||
gsize addr_size;
|
||||
guint n;
|
||||
guint i;
|
||||
gboolean is_routing;
|
||||
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"
|
||||
|
|
@ -85,24 +86,28 @@ dm_watch_cb(GPid pid, int status, gpointer user_data)
|
|||
}
|
||||
|
||||
static GPtrArray *
|
||||
create_dm_cmd_line(const char * iface,
|
||||
const NMIP4Config *ip4_config,
|
||||
const char * pidfile,
|
||||
gboolean announce_android_metered,
|
||||
GError ** error)
|
||||
create_dm_cmd_line(const char * iface,
|
||||
const NML3ConfigData *l3cd,
|
||||
const char * pidfile,
|
||||
gboolean announce_android_metered,
|
||||
GError ** error)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *cmd = NULL;
|
||||
nm_auto_free_gstring GString *s = NULL;
|
||||
char first[INET_ADDRSTRLEN];
|
||||
char last[INET_ADDRSTRLEN];
|
||||
char listen_address_s[INET_ADDRSTRLEN];
|
||||
char tmpaddr[INET_ADDRSTRLEN];
|
||||
char sbuf_addr[INET_ADDRSTRLEN];
|
||||
gs_free char * error_desc = NULL;
|
||||
const char * dm_binary;
|
||||
const NMPlatformIP4Address * listen_address;
|
||||
guint i, n;
|
||||
const in_addr_t * ipv4arr;
|
||||
const char *const * strarr;
|
||||
guint n;
|
||||
guint i;
|
||||
|
||||
listen_address = nm_ip4_config_get_first_address(ip4_config);
|
||||
listen_address = NMP_OBJECT_CAST_IP4_ADDRESS(
|
||||
nm_l3_config_data_get_first_obj(l3cd, NMP_OBJECT_TYPE_IP4_ADDRESS, NULL));
|
||||
|
||||
g_return_val_if_fail(listen_address, NULL);
|
||||
|
||||
|
|
@ -151,28 +156,28 @@ create_dm_cmd_line(const char * iface,
|
|||
|
||||
nm_strv_ptrarray_add_string_printf(cmd, "--dhcp-range=%s,%s,60m", first, last);
|
||||
|
||||
if (nm_ip4_config_best_default_route_get(ip4_config)) {
|
||||
if (nm_l3_config_data_get_best_default_route(l3cd, AF_INET)) {
|
||||
nm_strv_ptrarray_add_string_concat(cmd, "--dhcp-option=option:router,", listen_address_s);
|
||||
}
|
||||
|
||||
if ((n = nm_ip4_config_get_num_nameservers(ip4_config))) {
|
||||
ipv4arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &n);
|
||||
if (n > 0) {
|
||||
nm_gstring_prepare(&s);
|
||||
g_string_append(s, "--dhcp-option=option:dns-server");
|
||||
for (i = 0; i < n; i++) {
|
||||
g_string_append_c(s, ',');
|
||||
g_string_append(
|
||||
s,
|
||||
_nm_utils_inet4_ntop(nm_ip4_config_get_nameserver(ip4_config, i), tmpaddr));
|
||||
g_string_append(s, _nm_utils_inet4_ntop(ipv4arr[i], sbuf_addr));
|
||||
}
|
||||
nm_strv_ptrarray_take_gstring(cmd, &s);
|
||||
}
|
||||
|
||||
if ((n = nm_ip4_config_get_num_searches(ip4_config))) {
|
||||
strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &n);
|
||||
if (n > 0) {
|
||||
nm_gstring_prepare(&s);
|
||||
g_string_append(s, "--dhcp-option=option:domain-search");
|
||||
for (i = 0; i < n; i++) {
|
||||
g_string_append_c(s, ',');
|
||||
g_string_append(s, nm_ip4_config_get_search(ip4_config, i));
|
||||
g_string_append(s, strarr[i]);
|
||||
}
|
||||
nm_strv_ptrarray_take_gstring(cmd, &s);
|
||||
}
|
||||
|
|
@ -237,25 +242,25 @@ out:
|
|||
}
|
||||
|
||||
gboolean
|
||||
nm_dnsmasq_manager_start(NMDnsMasqManager *manager,
|
||||
NMIP4Config * ip4_config,
|
||||
gboolean announce_android_metered,
|
||||
GError ** error)
|
||||
nm_dnsmasq_manager_start(NMDnsMasqManager * manager,
|
||||
const NML3ConfigData *l3cd,
|
||||
gboolean announce_android_metered,
|
||||
GError ** error)
|
||||
{
|
||||
NMDnsMasqManagerPrivate *priv;
|
||||
gs_unref_ptrarray GPtrArray *dm_cmd = NULL;
|
||||
gs_free char * cmd_str = NULL;
|
||||
NMDnsMasqManagerPrivate * priv;
|
||||
|
||||
g_return_val_if_fail(NM_IS_DNSMASQ_MANAGER(manager), FALSE);
|
||||
g_return_val_if_fail(!error || !*error, FALSE);
|
||||
g_return_val_if_fail(nm_ip4_config_get_num_addresses(ip4_config) > 0, FALSE);
|
||||
g_return_val_if_fail(NM_IS_L3_CONFIG_DATA(l3cd), FALSE);
|
||||
g_return_val_if_fail(nm_l3_config_data_get_num_addresses(l3cd, AF_INET) > 0, FALSE);
|
||||
|
||||
priv = NM_DNSMASQ_MANAGER_GET_PRIVATE(manager);
|
||||
|
||||
kill_existing_by_pidfile(priv->pidfile);
|
||||
|
||||
dm_cmd =
|
||||
create_dm_cmd_line(priv->iface, ip4_config, priv->pidfile, announce_android_metered, error);
|
||||
dm_cmd = create_dm_cmd_line(priv->iface, l3cd, priv->pidfile, announce_android_metered, error);
|
||||
if (!dm_cmd)
|
||||
return FALSE;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@
|
|||
#ifndef __NETWORKMANAGER_DNSMASQ_MANAGER_H__
|
||||
#define __NETWORKMANAGER_DNSMASQ_MANAGER_H__
|
||||
|
||||
#include "nm-ip4-config.h"
|
||||
|
||||
#define NM_TYPE_DNSMASQ_MANAGER (nm_dnsmasq_manager_get_type())
|
||||
#define NM_DNSMASQ_MANAGER(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManager))
|
||||
|
|
@ -35,10 +33,10 @@ GType nm_dnsmasq_manager_get_type(void);
|
|||
|
||||
NMDnsMasqManager *nm_dnsmasq_manager_new(const char *iface);
|
||||
|
||||
gboolean nm_dnsmasq_manager_start(NMDnsMasqManager *manager,
|
||||
NMIP4Config * ip4_config,
|
||||
gboolean announce_android_metered,
|
||||
GError ** error);
|
||||
gboolean nm_dnsmasq_manager_start(NMDnsMasqManager * manager,
|
||||
const NML3ConfigData *l3cd,
|
||||
gboolean announce_android_metered,
|
||||
GError ** error);
|
||||
|
||||
void nm_dnsmasq_manager_stop(NMDnsMasqManager *manager);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
NMLndpNDiscPrivate * priv;
|
||||
int errsv;
|
||||
gs_unref_object NMNDisc *ndisc = NULL;
|
||||
NMLndpNDiscPrivate * priv;
|
||||
int errsv;
|
||||
|
||||
g_return_val_if_fail(NM_IS_PLATFORM(platform), NULL);
|
||||
g_return_val_if_fail(!error || !*error, NULL);
|
||||
g_return_val_if_fail(network_id, NULL);
|
||||
g_return_val_if_fail(config, NULL);
|
||||
g_return_val_if_fail(NM_IS_L3CFG(config->l3cfg), NULL);
|
||||
g_return_val_if_fail(config->network_id, NULL);
|
||||
|
||||
if (!nm_platform_netns_push(platform, &netns))
|
||||
return NULL;
|
||||
if (!nm_platform_netns_push(nm_l3cfg_get_platform(config->l3cfg), &netns)) {
|
||||
/* The inability to change the name space is also considered
|
||||
* a fatal error. We have a FD open to the file descriptor, and
|
||||
* it's unclear how to handle (or recover from) a failure to setns(). */
|
||||
g_return_val_if_reached(NULL);
|
||||
}
|
||||
|
||||
ndisc = g_object_new(NM_TYPE_LNDP_NDISC,
|
||||
NM_NDISC_PLATFORM,
|
||||
platform,
|
||||
NM_NDISC_STABLE_TYPE,
|
||||
(int) stable_type,
|
||||
NM_NDISC_IFINDEX,
|
||||
ifindex,
|
||||
NM_NDISC_IFNAME,
|
||||
ifname,
|
||||
NM_NDISC_NETWORK_ID,
|
||||
network_id,
|
||||
NM_NDISC_ADDR_GEN_MODE,
|
||||
(int) addr_gen_mode,
|
||||
NM_NDISC_NODE_TYPE,
|
||||
(int) node_type,
|
||||
NM_NDISC_MAX_ADDRESSES,
|
||||
max_addresses,
|
||||
NM_NDISC_ROUTER_SOLICITATIONS,
|
||||
router_solicitations,
|
||||
NM_NDISC_ROUTER_SOLICITATION_INTERVAL,
|
||||
router_solicitation_interval,
|
||||
NM_NDISC_RA_TIMEOUT,
|
||||
(guint) ra_timeout,
|
||||
NULL);
|
||||
ndisc = g_object_new(NM_TYPE_LNDP_NDISC, NM_NDISC_CONFIG, config, NULL);
|
||||
|
||||
priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc);
|
||||
|
||||
errsv = ndp_open(&priv->ndp);
|
||||
|
||||
if (errsv != 0) {
|
||||
errsv = nm_errno_native(errsv);
|
||||
g_set_error(error,
|
||||
NM_UTILS_ERROR,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"failure creating libndp socket: %s (%d)",
|
||||
nm_strerror_native(errsv),
|
||||
errsv);
|
||||
g_object_unref(ndisc);
|
||||
return NULL;
|
||||
/* This is serious. It might be ENOMEM or the inability to open (or modify)
|
||||
* a file descriptor. In all cases there is not much reason trying to recover
|
||||
* from that. File descriptors are a basic resource, that we just require (just
|
||||
* like memory). */
|
||||
g_return_val_if_reached(NULL);
|
||||
}
|
||||
return ndisc;
|
||||
|
||||
return g_steal_pointer(&ndisc);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -754,8 +721,9 @@ nm_lndp_ndisc_class_init(NMLndpNDiscClass *klass)
|
|||
NMNDiscClass *ndisc_class = NM_NDISC_CLASS(klass);
|
||||
|
||||
object_class->dispose = dispose;
|
||||
ndisc_class->start = start;
|
||||
ndisc_class->stop = stop;
|
||||
ndisc_class->send_rs = send_rs;
|
||||
ndisc_class->send_ra = send_ra;
|
||||
|
||||
ndisc_class->start = start;
|
||||
ndisc_class->stop = stop;
|
||||
ndisc_class->send_rs = send_rs;
|
||||
ndisc_class->send_ra = send_ra;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -54,38 +57,27 @@ struct _NMNDiscPrivate {
|
|||
GSource *timeout_expire_source;
|
||||
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
gboolean iid_is_token;
|
||||
|
||||
/* 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};
|
||||
|
||||
|
|
@ -115,14 +107,10 @@ 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)
|
||||
NMUtilsIPv6IfaceId * token)
|
||||
{
|
||||
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 +118,11 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
|
|||
|
||||
nm_l3_config_data_set_ip6_privacy(l3cd, ip6_privacy);
|
||||
|
||||
/* Check, whether kernel is recent enough to help user space handling RA.
|
||||
* If it's not supported, we have no ipv6-privacy and must add autoconf
|
||||
* addresses as /128. The reason for the /128 is to prevent the kernel
|
||||
* from adding a prefix route for this address. */
|
||||
ifa_flags = 0;
|
||||
if (kernel_support_extended_ifa_flags) {
|
||||
ifa_flags |= IFA_F_NOPREFIXROUTE;
|
||||
if (NM_IN_SET(ip6_privacy,
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
|
||||
ifa_flags |= IFA_F_MANAGETEMPADDR;
|
||||
plen = 64;
|
||||
} else
|
||||
plen = 128;
|
||||
ifa_flags = IFA_F_NOPREFIXROUTE;
|
||||
if (NM_IN_SET(ip6_privacy,
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
|
||||
ifa_flags |= IFA_F_MANAGETEMPADDR;
|
||||
|
||||
for (i = 0; i < rdata->addresses_n; i++) {
|
||||
const NMNDiscAddress *ndisc_addr = &rdata->addresses[i];
|
||||
|
|
@ -152,7 +131,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 +157,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 +169,13 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
|
|||
}
|
||||
|
||||
if (rdata->gateways_n > 0) {
|
||||
const NMIcmpv6RouterPref first_pref = rdata->gateways[0].preference;
|
||||
NMPlatformIP6Route r = {
|
||||
NMPlatformIP6Route r = {
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
|
||||
.ifindex = ifindex,
|
||||
.table_coerced = nm_platform_route_table_coerce(route_table),
|
||||
.metric = route_metric,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = 0,
|
||||
};
|
||||
|
||||
for (i = 0; i < rdata->gateways_n; i++) {
|
||||
|
|
@ -201,13 +183,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -222,6 +197,8 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
|
|||
nm_l3_config_data_set_ndisc_retrans_timer_msec(l3cd, rdata->retrans_timer_ms);
|
||||
|
||||
nm_l3_config_data_set_ip6_mtu(l3cd, rdata->mtu);
|
||||
if (token)
|
||||
nm_l3_config_data_set_ip6_token(l3cd, *token);
|
||||
|
||||
return g_steal_pointer(&l3cd);
|
||||
}
|
||||
|
|
@ -315,7 +292,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 +300,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 +308,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 +368,28 @@ _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_ndisc_data_to_l3cd(nm_l3cfg_get_multi_idx(priv->config.l3cfg),
|
||||
nm_l3cfg_get_ifindex(priv->config.l3cfg),
|
||||
rdata,
|
||||
priv->config.ip6_privacy,
|
||||
priv->iid_is_token ? &priv->iid : NULL);
|
||||
l3cd = nm_l3_config_data_seal(l3cd);
|
||||
|
||||
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 +469,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 +598,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 +889,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 +987,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;
|
||||
guint i;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -1048,20 +1090,21 @@ nm_ndisc_set_config(NMNDisc * ndisc,
|
|||
* Returns: %TRUE if addresses need to be regenerated, %FALSE otherwise.
|
||||
**/
|
||||
gboolean
|
||||
nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid)
|
||||
nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid, gboolean is_token)
|
||||
{
|
||||
NMNDiscPrivate * priv;
|
||||
NMNDiscDataInternal *rdata;
|
||||
|
||||
g_return_val_if_fail(NM_IS_NDISC(ndisc), FALSE);
|
||||
|
||||
priv = NM_NDISC_GET_PRIVATE(ndisc);
|
||||
rdata = &priv->rdata;
|
||||
priv = NM_NDISC_GET_PRIVATE(ndisc);
|
||||
priv->iid_is_token = is_token;
|
||||
rdata = &priv->rdata;
|
||||
|
||||
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 +1143,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 +1172,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 +1190,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 +1417,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 +1742,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 +1873,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 +1880,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 +1899,12 @@ nm_ndisc_class_init(NMNDiscClass *klass)
|
|||
object_class->dispose = dispose;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
obj_properties[PROP_PLATFORM] =
|
||||
g_param_spec_object(NM_NDISC_PLATFORM,
|
||||
"",
|
||||
"",
|
||||
NM_TYPE_PLATFORM,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_IFINDEX] =
|
||||
g_param_spec_int(NM_NDISC_IFINDEX,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
G_MAXINT,
|
||||
0,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_IFNAME] =
|
||||
g_param_spec_string(NM_NDISC_IFNAME,
|
||||
"",
|
||||
"",
|
||||
NULL,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_STABLE_TYPE] =
|
||||
g_param_spec_int(NM_NDISC_STABLE_TYPE,
|
||||
"",
|
||||
"",
|
||||
NM_UTILS_STABLE_TYPE_UUID,
|
||||
NM_UTILS_STABLE_TYPE_RANDOM,
|
||||
NM_UTILS_STABLE_TYPE_UUID,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_NETWORK_ID] =
|
||||
g_param_spec_string(NM_NDISC_NETWORK_ID,
|
||||
"",
|
||||
"",
|
||||
NULL,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_ADDR_GEN_MODE] =
|
||||
g_param_spec_int(NM_NDISC_ADDR_GEN_MODE,
|
||||
"",
|
||||
"",
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_MAX_ADDRESSES] =
|
||||
g_param_spec_int(NM_NDISC_MAX_ADDRESSES,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
G_MAXINT32,
|
||||
NM_NDISC_MAX_ADDRESSES_DEFAULT,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
G_STATIC_ASSERT_EXPR(G_MAXINT32 == NM_RA_TIMEOUT_INFINITY);
|
||||
obj_properties[PROP_RA_TIMEOUT] =
|
||||
g_param_spec_uint(NM_NDISC_RA_TIMEOUT,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
G_MAXINT32,
|
||||
0,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_ROUTER_SOLICITATIONS] =
|
||||
g_param_spec_int(NM_NDISC_ROUTER_SOLICITATIONS,
|
||||
"",
|
||||
"",
|
||||
1,
|
||||
G_MAXINT32,
|
||||
NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_ROUTER_SOLICITATION_INTERVAL] =
|
||||
g_param_spec_int(NM_NDISC_ROUTER_SOLICITATION_INTERVAL,
|
||||
"",
|
||||
"",
|
||||
1,
|
||||
G_MAXINT32,
|
||||
NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_NODE_TYPE] =
|
||||
g_param_spec_int(NM_NDISC_NODE_TYPE,
|
||||
"",
|
||||
"",
|
||||
NM_NDISC_NODE_TYPE_INVALID,
|
||||
NM_NDISC_NODE_TYPE_ROUTER,
|
||||
NM_NDISC_NODE_TYPE_INVALID,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
obj_properties[PROP_CONFIG] =
|
||||
g_param_spec_pointer(NM_NDISC_CONFIG,
|
||||
"",
|
||||
"",
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
|
||||
signals[CONFIG_RECEIVED] = g_signal_new(NM_NDISC_CONFIG_RECEIVED,
|
||||
|
|
@ -1947,9 +1915,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,21 +221,16 @@ 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);
|
||||
|
||||
gboolean nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid);
|
||||
gboolean nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid, gboolean is_token);
|
||||
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);
|
||||
|
|
@ -281,9 +280,6 @@ struct _NML3ConfigData *nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_id
|
|||
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);
|
||||
NMUtilsIPv6IfaceId * token);
|
||||
|
||||
#endif /* __NETWORKMANAGER_NDISC_H__ */
|
||||
|
|
|
|||
|
|
@ -11,24 +11,29 @@
|
|||
#include "ndisc/nm-fake-ndisc.h"
|
||||
|
||||
#include "platform/nm-fake-platform.h"
|
||||
#include "nm-netns.h"
|
||||
|
||||
#include "nm-test-utils-core.h"
|
||||
#include "platform/tests/test-common.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NMFakeNDisc *
|
||||
ndisc_new(void)
|
||||
{
|
||||
NMNDisc * ndisc;
|
||||
const int ifindex = 1;
|
||||
const char * ifname = nm_platform_link_get_name(NM_PLATFORM_GET, ifindex);
|
||||
NMUtilsIPv6IfaceId iid = {};
|
||||
gs_unref_object NML3Cfg *l3cfg = NULL;
|
||||
NMNDisc * ndisc;
|
||||
const int ifindex = 1;
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
|
||||
ndisc = nm_fake_ndisc_new(ifindex, ifname);
|
||||
iid.id_u8[7] = 1;
|
||||
nm_ndisc_set_iid(ndisc, iid);
|
||||
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, FALSE);
|
||||
|
||||
return NM_FAKE_NDISC(ndisc);
|
||||
}
|
||||
|
||||
|
|
@ -140,9 +145,15 @@ typedef struct {
|
|||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_simple_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data)
|
||||
test_simple_changed(NMNDisc * ndisc,
|
||||
const NMNDiscData * rdata,
|
||||
guint changed_i,
|
||||
const NML3ConfigData *l3cd,
|
||||
TestData * data)
|
||||
{
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
NMNDiscConfigMap changed = changed_i;
|
||||
|
||||
_LOGT("test_simple: callback (counter=%u)", data->counter);
|
||||
|
||||
switch (data->counter++) {
|
||||
case 0:
|
||||
|
|
@ -206,9 +217,11 @@ test_simple(void)
|
|||
|
||||
g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_simple_changed), &data);
|
||||
|
||||
_LOGT("test_simple: start");
|
||||
nm_ndisc_start(NM_NDISC(ndisc));
|
||||
nmtst_main_loop_run_assert(data.loop, 15000);
|
||||
g_assert_cmpint(data.counter, ==, 2);
|
||||
_LOGT("test_simple: done");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -221,9 +234,13 @@ test_everything_rs_sent(NMNDisc *ndisc, TestData *data)
|
|||
}
|
||||
|
||||
static void
|
||||
test_everything_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data)
|
||||
test_everything_changed(NMNDisc * ndisc,
|
||||
const NMNDiscData * rdata,
|
||||
guint changed_i,
|
||||
const NML3ConfigData *l3cd,
|
||||
TestData * data)
|
||||
{
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
NMNDiscConfigMap changed = changed_i;
|
||||
|
||||
if (data->counter == 0) {
|
||||
g_assert_cmpint(data->rs_counter, ==, 1);
|
||||
|
|
@ -342,12 +359,13 @@ test_everything(void)
|
|||
}
|
||||
|
||||
static void
|
||||
test_preference_order_cb(NMNDisc * ndisc,
|
||||
const NMNDiscData *rdata,
|
||||
guint changed_int,
|
||||
TestData * data)
|
||||
test_preference_order_cb(NMNDisc * ndisc,
|
||||
const NMNDiscData * rdata,
|
||||
guint changed_i,
|
||||
const NML3ConfigData *l3cd,
|
||||
TestData * data)
|
||||
{
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
NMNDiscConfigMap changed = changed_i;
|
||||
|
||||
if (data->counter == 1) {
|
||||
g_assert_cmpint(changed,
|
||||
|
|
@ -434,12 +452,13 @@ test_preference_order(void)
|
|||
}
|
||||
|
||||
static void
|
||||
test_preference_changed_cb(NMNDisc * ndisc,
|
||||
const NMNDiscData *rdata,
|
||||
guint changed_int,
|
||||
TestData * data)
|
||||
test_preference_changed_cb(NMNDisc * ndisc,
|
||||
const NMNDiscData * rdata,
|
||||
guint changed_i,
|
||||
const NML3ConfigData *l3cd,
|
||||
TestData * data)
|
||||
{
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
NMNDiscConfigMap changed = changed_i;
|
||||
|
||||
if (data->counter == 1) {
|
||||
g_assert_cmpint(changed,
|
||||
|
|
@ -576,10 +595,11 @@ test_preference_changed(void)
|
|||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_test_dns_solicit_loop_changed(NMNDisc * ndisc,
|
||||
const NMNDiscData *rdata,
|
||||
guint changed_int,
|
||||
TestData * data)
|
||||
_test_dns_solicit_loop_changed(NMNDisc * ndisc,
|
||||
const NMNDiscData * rdata,
|
||||
guint changed_i,
|
||||
const NML3ConfigData *l3cd,
|
||||
TestData * data)
|
||||
{
|
||||
data->counter++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include "ndisc/nm-lndp-ndisc.h"
|
||||
|
||||
#include "libnm-platform/nm-linux-platform.h"
|
||||
#include "nm-netns.h"
|
||||
#include "nm-l3cfg.h"
|
||||
|
||||
#include "nm-test-utils-core.h"
|
||||
|
||||
|
|
@ -19,16 +21,18 @@ NMTST_DEFINE();
|
|||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
GMainLoop * loop;
|
||||
NMNDisc * ndisc;
|
||||
int ifindex = 1;
|
||||
const char * ifname;
|
||||
NMUtilsIPv6IfaceId iid = {};
|
||||
GError * error = NULL;
|
||||
int max_addresses;
|
||||
int router_solicitations;
|
||||
int router_solicitation_interval;
|
||||
guint32 ra_timeout;
|
||||
gs_unref_object NML3Cfg *l3cfg = NULL;
|
||||
NMNDiscConfig config;
|
||||
GMainLoop * loop;
|
||||
NMNDisc * ndisc;
|
||||
int ifindex = 1;
|
||||
const char * ifname;
|
||||
NMUtilsIPv6IfaceId iid = {};
|
||||
GError * error = NULL;
|
||||
int max_addresses;
|
||||
int router_solicitations;
|
||||
int router_solicitation_interval;
|
||||
guint32 ra_timeout;
|
||||
|
||||
nmtst_init_with_logging(&argc, &argv, NULL, "DEFAULT");
|
||||
|
||||
|
|
@ -56,18 +60,23 @@ main(int argc, char **argv)
|
|||
&router_solicitation_interval,
|
||||
&ra_timeout);
|
||||
|
||||
ndisc = nm_lndp_ndisc_new(NM_PLATFORM_GET,
|
||||
ifindex,
|
||||
ifname,
|
||||
NM_UTILS_STABLE_TYPE_UUID,
|
||||
"8ce666e8-d34d-4fb1-b858-f15a7al28086",
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
|
||||
NM_NDISC_NODE_TYPE_HOST,
|
||||
max_addresses,
|
||||
router_solicitations,
|
||||
router_solicitation_interval,
|
||||
ra_timeout,
|
||||
&error);
|
||||
l3cfg = nm_netns_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);
|
||||
|
|
@ -75,7 +84,7 @@ main(int argc, char **argv)
|
|||
}
|
||||
|
||||
iid.id_u8[7] = 1;
|
||||
nm_ndisc_set_iid(ndisc, iid);
|
||||
nm_ndisc_set_iid(ndisc, iid, FALSE);
|
||||
nm_ndisc_start(ndisc);
|
||||
g_main_loop_run(loop);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@
|
|||
#include "settings/nm-settings-connection.h"
|
||||
|
||||
typedef struct {
|
||||
CList call_ids_lst_head;
|
||||
NMFirewallConfig *firewall_config;
|
||||
CList call_ids_lst_head;
|
||||
} NMActRequestPrivate;
|
||||
|
||||
struct _NMActRequest {
|
||||
|
|
@ -250,36 +249,6 @@ nm_act_request_clear_secrets(NMActRequest *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMFirewallConfig *
|
||||
nm_act_request_get_shared(NMActRequest *req)
|
||||
{
|
||||
g_return_val_if_fail(NM_IS_ACT_REQUEST(req), FALSE);
|
||||
|
||||
return NM_ACT_REQUEST_GET_PRIVATE(req)->firewall_config;
|
||||
}
|
||||
|
||||
void
|
||||
nm_act_request_set_shared(NMActRequest *req, NMFirewallConfig *rules)
|
||||
{
|
||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(req);
|
||||
|
||||
g_return_if_fail(NM_IS_ACT_REQUEST(req));
|
||||
|
||||
if (priv->firewall_config == rules)
|
||||
return;
|
||||
|
||||
if (priv->firewall_config) {
|
||||
nm_firewall_config_apply(priv->firewall_config, FALSE);
|
||||
priv->firewall_config = NULL;
|
||||
}
|
||||
if (rules) {
|
||||
priv->firewall_config = rules;
|
||||
nm_firewall_config_apply(priv->firewall_config, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
device_notify(GObject *object, GParamSpec *pspec, gpointer self)
|
||||
{
|
||||
|
|
@ -508,11 +477,6 @@ dispose(GObject *object)
|
|||
c_list_for_each_entry_safe (call_id, call_id_safe, &priv->call_ids_lst_head, call_ids_lst)
|
||||
_do_cancel_secrets(self, call_id, TRUE);
|
||||
|
||||
if (priv->firewall_config) {
|
||||
nm_firewall_config_apply(priv->firewall_config, FALSE);
|
||||
nm_clear_pointer(&priv->firewall_config, nm_firewall_config_free);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS(nm_act_request_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,6 +929,59 @@ nm_global_dns_config_is_empty(const NMGlobalDnsConfig *dns_config)
|
|||
return !dns_config->searches && !dns_config->options && !dns_config->domain_list;
|
||||
}
|
||||
|
||||
int
|
||||
nm_global_dns_config_cmp(const NMGlobalDnsConfig *a,
|
||||
const NMGlobalDnsConfig *b,
|
||||
gboolean check_internal)
|
||||
{
|
||||
guint i;
|
||||
|
||||
NM_CMP_SELF(a, b);
|
||||
|
||||
NM_CMP_RETURN(
|
||||
nm_strv_cmp_n(a->searches ?: NM_STRV_EMPTY(), -1, b->searches ?: NM_STRV_EMPTY(), -1));
|
||||
|
||||
NM_CMP_RETURN(
|
||||
nm_strv_cmp_n(a->options ?: NM_STRV_EMPTY(), -1, b->options ?: NM_STRV_EMPTY(), -1));
|
||||
|
||||
NM_CMP_RETURN(nm_strv_cmp_n(a->domain_list ?: NM_STRV_EMPTY_CC(),
|
||||
-1,
|
||||
b->domain_list ?: NM_STRV_EMPTY_CC(),
|
||||
-1));
|
||||
|
||||
if (a->domain_list) {
|
||||
for (i = 0; a->domain_list[i]; i++) {
|
||||
const NMGlobalDnsDomain *domain_a;
|
||||
const NMGlobalDnsDomain *domain_b;
|
||||
|
||||
nm_assert(nm_streq(a->domain_list[i], b->domain_list[i]));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
nm_global_dns_config_update_checksum(const NMGlobalDnsConfig *dns_config, GChecksum *sum)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -264,6 +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);
|
||||
int nm_global_dns_config_cmp(const NMGlobalDnsConfig *a,
|
||||
const NMGlobalDnsConfig *b,
|
||||
gboolean check_internal);
|
||||
void nm_global_dns_config_update_checksum(const NMGlobalDnsConfig *dns_config, GChecksum *sum);
|
||||
void nm_global_dns_config_free(NMGlobalDnsConfig *dns_config);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
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,
|
||||
NM_CONFIG_KEYFILE_GROUP_MAIN,
|
||||
"configure-and-quit",
|
||||
TRUE);
|
||||
g_key_file_set_string(keyfile,
|
||||
NM_CONFIG_KEYFILE_GROUP_MAIN,
|
||||
"configure-and-quit",
|
||||
"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;
|
||||
GVariantBuilder int_builder;
|
||||
NMDedupMultiIter ipconf_iter;
|
||||
GVariant * var1;
|
||||
GVariant * var2;
|
||||
guint n;
|
||||
guint i;
|
||||
const NMPObject *default_route;
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
const NMPObject * obj;
|
||||
GVariantBuilder int_builder;
|
||||
NMDedupMultiIter ipconf_iter;
|
||||
GVariant * var1;
|
||||
GVariant * var2;
|
||||
guint n;
|
||||
guint i;
|
||||
const NMPObject * default_route;
|
||||
const char *const *strarr;
|
||||
const in_addr_t * ip4arr;
|
||||
gconstpointer iparr;
|
||||
|
||||
if (IS_IPv4)
|
||||
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aau"));
|
||||
else
|
||||
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("a(ayuay)"));
|
||||
default_route = nm_ip_config_best_default_route_get(ip);
|
||||
if (IS_IPv4)
|
||||
nm_ip_config_iter_ip4_address_init(&ipconf_iter, NM_IP4_CONFIG(ip));
|
||||
else
|
||||
nm_ip_config_iter_ip6_address_init(&ipconf_iter, NM_IP6_CONFIG(ip));
|
||||
while (nm_platform_dedup_multi_iter_next_obj(&ipconf_iter,
|
||||
&obj,
|
||||
NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4))) {
|
||||
default_route = nm_l3_config_data_get_best_default_route(l3cd, addr_family);
|
||||
nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
|
||||
l3cd,
|
||||
&obj,
|
||||
NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) {
|
||||
const NMPlatformIPXAddress *addr = NMP_OBJECT_CAST_IPX_ADDRESS(obj);
|
||||
|
||||
if (IS_IPv4) {
|
||||
|
|
@ -225,30 +220,28 @@ dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder)
|
|||
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au"));
|
||||
else
|
||||
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aay"));
|
||||
n = nm_ip_config_get_num_nameservers(ip);
|
||||
iparr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &n);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (IS_IPv4) {
|
||||
g_variant_builder_add(&int_builder,
|
||||
"u",
|
||||
nm_ip4_config_get_nameserver(NM_IP4_CONFIG(ip), i));
|
||||
} else {
|
||||
var1 = nm_g_variant_new_ay_in6addr(nm_ip6_config_get_nameserver(NM_IP6_CONFIG(ip), i));
|
||||
if (IS_IPv4)
|
||||
g_variant_builder_add(&int_builder, "u", ((const in_addr_t *) iparr)[i]);
|
||||
else {
|
||||
var1 = nm_g_variant_new_ay_in6addr(&(((const struct in6_addr *) iparr)[i]));
|
||||
g_variant_builder_add(&int_builder, "@ay", var1);
|
||||
}
|
||||
}
|
||||
g_variant_builder_add(builder, "{sv}", "nameservers", g_variant_builder_end(&int_builder));
|
||||
|
||||
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("as"));
|
||||
n = nm_ip_config_get_num_domains(ip);
|
||||
strarr = nm_l3_config_data_get_domains(l3cd, addr_family, &n);
|
||||
for (i = 0; i < n; i++)
|
||||
g_variant_builder_add(&int_builder, "s", nm_ip_config_get_domain(ip, i));
|
||||
g_variant_builder_add(&int_builder, "s", strarr[i]);
|
||||
g_variant_builder_add(builder, "{sv}", "domains", g_variant_builder_end(&int_builder));
|
||||
|
||||
if (IS_IPv4) {
|
||||
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au"));
|
||||
n = nm_ip4_config_get_num_wins(NM_IP4_CONFIG(ip));
|
||||
ip4arr = nm_l3_config_data_get_wins(l3cd, &n);
|
||||
for (i = 0; i < n; i++)
|
||||
g_variant_builder_add(&int_builder, "u", nm_ip4_config_get_wins(NM_IP4_CONFIG(ip), i));
|
||||
g_variant_builder_add(&int_builder, "u", ip4arr[i]);
|
||||
g_variant_builder_add(builder, "{sv}", "wins-servers", g_variant_builder_end(&int_builder));
|
||||
}
|
||||
|
||||
|
|
@ -256,13 +249,10 @@ dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder)
|
|||
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aau"));
|
||||
else
|
||||
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("a(ayuayu)"));
|
||||
if (IS_IPv4)
|
||||
nm_ip_config_iter_ip4_route_init(&ipconf_iter, NM_IP4_CONFIG(ip));
|
||||
else
|
||||
nm_ip_config_iter_ip6_route_init(&ipconf_iter, NM_IP6_CONFIG(ip));
|
||||
while (nm_platform_dedup_multi_iter_next_obj(&ipconf_iter,
|
||||
&obj,
|
||||
NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))) {
|
||||
nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
|
||||
l3cd,
|
||||
&obj,
|
||||
NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) {
|
||||
const NMPlatformIPXRoute *route = NMP_OBJECT_CAST_IPX_ROUTE(obj);
|
||||
|
||||
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
|
||||
|
|
@ -299,10 +289,8 @@ fill_device_props(NMDevice * device,
|
|||
GVariant ** dhcp4_props,
|
||||
GVariant ** dhcp6_props)
|
||||
{
|
||||
NMProxyConfig *proxy_config;
|
||||
NMIP4Config * ip4_config;
|
||||
NMIP6Config * ip6_config;
|
||||
NMDhcpConfig * dhcp_config;
|
||||
const NML3ConfigData *l3cd;
|
||||
NMDhcpConfig * dhcp_config;
|
||||
|
||||
/* If the action is for a VPN, send the VPN's IP interface instead of the device's */
|
||||
g_variant_builder_add(dev_builder,
|
||||
|
|
@ -329,17 +317,12 @@ fill_device_props(NMDevice * device,
|
|||
g_variant_new_object_path(nm_dbus_object_get_path(NM_DBUS_OBJECT(device))));
|
||||
}
|
||||
|
||||
proxy_config = nm_device_get_proxy_config(device);
|
||||
if (proxy_config)
|
||||
dump_proxy_to_props(proxy_config, proxy_builder);
|
||||
|
||||
ip4_config = nm_device_get_ip4_config(device);
|
||||
if (ip4_config)
|
||||
dump_ip_to_props(NM_IP_CONFIG(ip4_config), ip4_builder);
|
||||
|
||||
ip6_config = nm_device_get_ip6_config(device);
|
||||
if (ip6_config)
|
||||
dump_ip_to_props(NM_IP_CONFIG(ip6_config), ip6_builder);
|
||||
l3cd = nm_device_get_l3cd(device, TRUE);
|
||||
if (l3cd) {
|
||||
dump_ip_to_props(l3cd, AF_INET, ip4_builder);
|
||||
dump_ip_to_props(l3cd, AF_INET6, ip6_builder);
|
||||
dump_proxy_to_props(l3cd, proxy_builder);
|
||||
}
|
||||
|
||||
dhcp_config = nm_device_get_dhcp_config(device, AF_INET);
|
||||
if (dhcp_config)
|
||||
|
|
@ -351,19 +334,16 @@ fill_device_props(NMDevice * device,
|
|||
}
|
||||
|
||||
static void
|
||||
fill_vpn_props(NMProxyConfig * proxy_config,
|
||||
NMIP4Config * ip4_config,
|
||||
NMIP6Config * ip6_config,
|
||||
GVariantBuilder *proxy_builder,
|
||||
GVariantBuilder *ip4_builder,
|
||||
GVariantBuilder *ip6_builder)
|
||||
fill_vpn_props(const NML3ConfigData *l3cd,
|
||||
GVariantBuilder * proxy_builder,
|
||||
GVariantBuilder * ip4_builder,
|
||||
GVariantBuilder * ip6_builder)
|
||||
{
|
||||
if (proxy_config)
|
||||
dump_proxy_to_props(proxy_config, proxy_builder);
|
||||
if (ip4_config)
|
||||
dump_ip_to_props(NM_IP_CONFIG(ip4_config), ip4_builder);
|
||||
if (ip6_config)
|
||||
dump_ip_to_props(NM_IP_CONFIG(ip6_config), ip6_builder);
|
||||
if (l3cd) {
|
||||
dump_ip_to_props(l3cd, AF_INET, ip4_builder);
|
||||
dump_ip_to_props(l3cd, AF_INET6, ip6_builder);
|
||||
dump_proxy_to_props(l3cd, proxy_builder);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
|
@ -479,9 +459,7 @@ _dispatcher_call(NMDispatcherAction action,
|
|||
gboolean activation_type_external,
|
||||
NMConnectivityState connectivity_state,
|
||||
const char * vpn_iface,
|
||||
NMProxyConfig * vpn_proxy_config,
|
||||
NMIP4Config * vpn_ip4_config,
|
||||
NMIP6Config * vpn_ip6_config,
|
||||
const NML3ConfigData *l3cd,
|
||||
NMDispatcherFunc callback,
|
||||
gpointer user_data,
|
||||
NMDispatcherCallId ** out_call_id)
|
||||
|
|
@ -593,13 +571,8 @@ _dispatcher_call(NMDispatcherAction action,
|
|||
&device_ip6_props,
|
||||
&device_dhcp4_props,
|
||||
&device_dhcp6_props);
|
||||
if (vpn_ip4_config || vpn_ip6_config) {
|
||||
fill_vpn_props(vpn_proxy_config,
|
||||
vpn_ip4_config,
|
||||
vpn_ip6_config,
|
||||
&vpn_proxy_props,
|
||||
&vpn_ip4_props,
|
||||
&vpn_ip6_props);
|
||||
if (l3cd) {
|
||||
fill_vpn_props(l3cd, &vpn_proxy_props, &vpn_ip4_props, &vpn_ip6_props);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -693,8 +666,6 @@ nm_dispatcher_call_hostname(NMDispatcherFunc callback,
|
|||
NM_CONNECTIVITY_UNKNOWN,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
callback,
|
||||
user_data,
|
||||
out_call_id);
|
||||
|
|
@ -744,8 +715,6 @@ nm_dispatcher_call_device(NMDispatcherAction action,
|
|||
NM_CONNECTIVITY_UNKNOWN,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
callback,
|
||||
user_data,
|
||||
out_call_id);
|
||||
|
|
@ -790,8 +759,6 @@ nm_dispatcher_call_device_sync(NMDispatcherAction action,
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
|
@ -802,9 +769,7 @@ nm_dispatcher_call_device_sync(NMDispatcherAction action,
|
|||
* @applied_connection: the currently applied connection
|
||||
* @parent_device: the parent #NMDevice of the VPN connection
|
||||
* @vpn_iface: the IP interface of the VPN tunnel, if any
|
||||
* @vpn_proxy_config: the #NMProxyConfig of the VPN connection
|
||||
* @vpn_ip4_config: the #NMIP4Config of the VPN connection
|
||||
* @vpn_ip6_config: the #NMIP6Config of the VPN connection
|
||||
* @vpn_l3cd: the #NML3ConfigData of the VPN connection
|
||||
* @callback: a caller-supplied callback to execute when done
|
||||
* @user_data: caller-supplied pointer passed to @callback
|
||||
* @out_call_id: on success, a call identifier which can be passed to
|
||||
|
|
@ -821,9 +786,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
|
|||
NMConnection * applied_connection,
|
||||
NMDevice * parent_device,
|
||||
const char * vpn_iface,
|
||||
NMProxyConfig * vpn_proxy_config,
|
||||
NMIP4Config * vpn_ip4_config,
|
||||
NMIP6Config * vpn_ip6_config,
|
||||
const NML3ConfigData *l3cd,
|
||||
NMDispatcherFunc callback,
|
||||
gpointer user_data,
|
||||
NMDispatcherCallId ** out_call_id)
|
||||
|
|
@ -836,9 +799,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
|
|||
FALSE,
|
||||
NM_CONNECTIVITY_UNKNOWN,
|
||||
vpn_iface,
|
||||
vpn_proxy_config,
|
||||
vpn_ip4_config,
|
||||
vpn_ip6_config,
|
||||
l3cd,
|
||||
callback,
|
||||
user_data,
|
||||
out_call_id);
|
||||
|
|
@ -851,9 +812,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
|
|||
* @applied_connection: the currently applied connection
|
||||
* @parent_device: the parent #NMDevice of the VPN connection
|
||||
* @vpn_iface: the IP interface of the VPN tunnel, if any
|
||||
* @vpn_proxy_config: the #NMProxyConfig of the VPN connection
|
||||
* @vpn_ip4_config: the #NMIP4Config of the VPN connection
|
||||
* @vpn_ip6_config: the #NMIP6Config of the VPN connection
|
||||
* @vpn_l3cd: the #NML3ConfigData of the VPN connection
|
||||
*
|
||||
* This method always invokes the dispatcher action synchronously and it may
|
||||
* take a long time to return.
|
||||
|
|
@ -866,9 +825,7 @@ nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
|
|||
NMConnection * applied_connection,
|
||||
NMDevice * parent_device,
|
||||
const char * vpn_iface,
|
||||
NMProxyConfig * vpn_proxy_config,
|
||||
NMIP4Config * vpn_ip4_config,
|
||||
NMIP6Config * vpn_ip6_config)
|
||||
const NML3ConfigData *l3cd)
|
||||
{
|
||||
return _dispatcher_call(action,
|
||||
TRUE,
|
||||
|
|
@ -878,9 +835,7 @@ nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
|
|||
FALSE,
|
||||
NM_CONNECTIVITY_UNKNOWN,
|
||||
vpn_iface,
|
||||
vpn_proxy_config,
|
||||
vpn_ip4_config,
|
||||
vpn_ip6_config,
|
||||
l3cd,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
|
@ -913,8 +868,6 @@ nm_dispatcher_call_connectivity(NMConnectivityState connectivity_state,
|
|||
connectivity_state,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
callback,
|
||||
user_data,
|
||||
out_call_id);
|
||||
|
|
|
|||
|
|
@ -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,130 @@
|
|||
|
||||
#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)
|
||||
{
|
||||
NMIPConfig * self = NM_IP_CONFIG(object);
|
||||
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
|
||||
if (len > 0) {
|
||||
nm_assert(strv && strv[0]);
|
||||
g_value_set_variant(value, g_variant_new_strv((const char *const *) strv, len));
|
||||
} else
|
||||
g_value_set_variant(value, nm_g_variant_singleton_as());
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_l3cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMIPConfig *self)
|
||||
{
|
||||
switch (notify_data->notify_type) {
|
||||
case NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED:
|
||||
if (notify_data->l3cd_changed.commited)
|
||||
_handle_l3cd_changed(self, notify_data->l3cd_changed.l3cd_new);
|
||||
break;
|
||||
case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE:
|
||||
_handle_platform_change(self, notify_data->platform_change_on_idle.obj_type_flags, FALSE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
get_property_ip(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMIPConfig * self = NM_IP_CONFIG(object);
|
||||
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
|
||||
const int addr_family = nm_ip_config_get_addr_family(self);
|
||||
char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN];
|
||||
const char *const *strv;
|
||||
guint len;
|
||||
int v_i;
|
||||
|
||||
(void) priv;
|
||||
switch (prop_id) {
|
||||
case PROP_IP_ADDRESS_DATA:
|
||||
g_value_set_variant(value, priv->v_address_data);
|
||||
break;
|
||||
case PROP_IP_GATEWAY:
|
||||
if (priv->v_gateway.best_default_route) {
|
||||
const NMIPAddr *gateway;
|
||||
|
||||
gateway = nm_platform_ip_route_get_gateway(
|
||||
addr_family,
|
||||
NMP_OBJECT_CAST_IP_ROUTE(priv->v_gateway.best_default_route));
|
||||
g_value_set_variant(
|
||||
value,
|
||||
g_variant_new_string(nm_utils_inet_ntop(addr_family, gateway, sbuf_addr)));
|
||||
} else
|
||||
g_value_set_variant(value, nm_g_variant_singleton_s_empty());
|
||||
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 +143,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 +162,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 +174,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 +225,680 @@ 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);
|
||||
}
|
||||
|
||||
void
|
||||
nm_ip_config_dns_hash(const NML3ConfigData *l3cd, GChecksum *sum, int addr_family)
|
||||
{
|
||||
guint i;
|
||||
int val;
|
||||
const char *const *nameservers;
|
||||
const in_addr_t * wins;
|
||||
const char *const *domains;
|
||||
const char *const *searches;
|
||||
const char *const *options;
|
||||
guint num_nameservers;
|
||||
guint num_wins;
|
||||
guint num_domains;
|
||||
guint num_searches;
|
||||
guint num_options;
|
||||
|
||||
g_return_if_fail(l3cd);
|
||||
g_return_if_fail(sum);
|
||||
|
||||
nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers);
|
||||
for (i = 0; i < num_nameservers; i++) {
|
||||
g_checksum_update(sum,
|
||||
nm_ip_addr_from_packed_array(addr_family, nameservers, i),
|
||||
nm_utils_addr_family_to_size(addr_family));
|
||||
}
|
||||
|
||||
if (addr_family == AF_INET) {
|
||||
wins = nm_l3_config_data_get_wins(l3cd, &num_wins);
|
||||
for (i = 0; i < num_wins; i++)
|
||||
g_checksum_update(sum, (guint8 *) &wins[i], 4);
|
||||
}
|
||||
|
||||
domains = nm_l3_config_data_get_domains(l3cd, addr_family, &num_domains);
|
||||
for (i = 0; i < num_domains; i++) {
|
||||
g_checksum_update(sum, (const guint8 *) domains[i], strlen(domains[i]));
|
||||
}
|
||||
|
||||
searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches);
|
||||
for (i = 0; i < num_searches; i++) {
|
||||
g_checksum_update(sum, (const guint8 *) searches[i], strlen(searches[i]));
|
||||
}
|
||||
|
||||
options = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num_options);
|
||||
for (i = 0; i < num_options; i++) {
|
||||
g_checksum_update(sum, (const guint8 *) options[i], strlen(options[i]));
|
||||
}
|
||||
|
||||
val = nm_l3_config_data_get_mdns(l3cd);
|
||||
if (val != NM_SETTING_CONNECTION_MDNS_DEFAULT)
|
||||
g_checksum_update(sum, (const guint8 *) &val, sizeof(val));
|
||||
|
||||
val = nm_l3_config_data_get_llmnr(l3cd);
|
||||
if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT)
|
||||
g_checksum_update(sum, (const guint8 *) &val, sizeof(val));
|
||||
|
||||
val = nm_l3_config_data_get_dns_over_tls(l3cd);
|
||||
if (val != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT)
|
||||
g_checksum_update(sum, (const guint8 *) &val, sizeof(val));
|
||||
|
||||
/* FIXME(ip-config-checksum): the DNS priority should be considered relevant
|
||||
* and added into the checksum as well, but this can't be done right now
|
||||
* because in the DNS manager we rely on the fact that an empty
|
||||
* configuration (i.e. just created) has a zero checksum. This is needed to
|
||||
* avoid rewriting resolv.conf when there is no change.
|
||||
*
|
||||
* The DNS priority initial value depends on the connection type (VPN or
|
||||
* not), so it's a bit difficult to add it to checksum maintaining the
|
||||
* assumption of checksum(empty)=0
|
||||
*/
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* 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 (priv->v_gateway.best_default_route != best_default_route) {
|
||||
if (!nm_ip_addr_equal(
|
||||
addr_family,
|
||||
nm_platform_ip_route_get_gateway(
|
||||
addr_family,
|
||||
NMP_OBJECT_CAST_IP_ROUTE(priv->v_gateway.best_default_route)),
|
||||
nm_platform_ip_route_get_gateway(addr_family,
|
||||
NMP_OBJECT_CAST_IP_ROUTE(best_default_route))))
|
||||
best_default_route_changed = TRUE;
|
||||
|
||||
nmp_object_ref_set(&priv->v_gateway.best_default_route, best_default_route);
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -19,26 +20,67 @@
|
|||
#define NM_IP_CONFIG_GET_CLASS(obj) \
|
||||
(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"
|
||||
#define NM_IP_CONFIG_L3CFG "l3cfg"
|
||||
|
||||
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;
|
||||
} v_gateway;
|
||||
gulong l3cfg_notify_id;
|
||||
};
|
||||
|
||||
struct _NMIPConfig {
|
||||
NMDBusObject parent;
|
||||
struct _NMIPConfigPrivate *_priv;
|
||||
NMDBusObject parent;
|
||||
struct _NMIPConfigPrivate _priv;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
NMDBusObjectClass parent;
|
||||
gboolean is_ipv4;
|
||||
int addr_family;
|
||||
} NMIPConfigClass;
|
||||
|
||||
GType nm_ip_config_get_type(void);
|
||||
GType nm_ip4_config_get_type(void);
|
||||
GType nm_ip6_config_get_type(void);
|
||||
|
||||
NMIPConfig *nm_ip_config_new(int addr_family, NML3Cfg *l3cfg, gboolean is_vpn);
|
||||
NMIPConfig *nm_ip_config_new(int addr_family, NML3Cfg *l3cfg);
|
||||
|
||||
void nm_ip_config_take_and_unexport_on_idle(NMIPConfig *self_take);
|
||||
|
||||
void nm_ip_config_dns_hash(const NML3ConfigData *l3cd, GChecksum *sum, int addr_family);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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__ */
|
||||
|
|
@ -117,8 +117,10 @@ struct _NML3ConfigData {
|
|||
NMIPRouteTableSyncMode route_table_sync_x[2];
|
||||
};
|
||||
|
||||
NMSettingConnectionMdns mdns;
|
||||
NMSettingConnectionLlmnr llmnr;
|
||||
NMSettingConnectionMdns mdns;
|
||||
NMSettingConnectionLlmnr llmnr;
|
||||
NMSettingConnectionDnsOverTls dns_over_tls;
|
||||
NMUtilsIPv6IfaceId ip6_token;
|
||||
|
||||
NML3ConfigDatFlags flags;
|
||||
|
||||
|
|
@ -570,6 +572,21 @@ 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->ip6_token.id != 0) {
|
||||
_L("ipv6-token: %s",
|
||||
nm_utils_inet6_interface_identifier_to_token(&self->ip6_token, sbuf_addr));
|
||||
}
|
||||
|
||||
if (self->metered != NM_TERNARY_DEFAULT)
|
||||
_L("metered: %s", self->metered ? "yes" : "no");
|
||||
|
||||
|
|
@ -666,6 +683,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 +1697,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)
|
||||
{
|
||||
|
|
@ -1817,6 +1855,26 @@ nm_l3_config_data_set_ip6_privacy(NML3ConfigData *self, NMSettingIP6ConfigPrivac
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
NMUtilsIPv6IfaceId
|
||||
nm_l3_config_data_get_ip6_token(const NML3ConfigData *self)
|
||||
{
|
||||
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
|
||||
|
||||
return self->ip6_token;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_l3_config_data_set_ip6_token(NML3ConfigData *self, NMUtilsIPv6IfaceId ipv6_token)
|
||||
{
|
||||
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
|
||||
|
||||
if (self->ip6_token.id == ipv6_token.id)
|
||||
return FALSE;
|
||||
|
||||
self->ip6_token.id = ipv6_token.id;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NMProxyConfigMethod
|
||||
nm_l3_config_data_get_proxy_method(const NML3ConfigData *self)
|
||||
{
|
||||
|
|
@ -2125,6 +2183,8 @@ 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->ip6_token.id, b->ip6_token.id);
|
||||
NM_CMP_DIRECT(a->mtu, b->mtu);
|
||||
NM_CMP_DIRECT(a->ip6_mtu, b->ip6_mtu);
|
||||
NM_CMP_DIRECT_UNSAFE(a->metered, b->metered);
|
||||
|
|
@ -2325,7 +2385,8 @@ nm_l3_config_data_add_dependent_onlink_routes(NML3ConfigData *self, int addr_fam
|
|||
if (nm_ip_addr_is_null(addr_family, p_gateway))
|
||||
continue;
|
||||
|
||||
if (_data_get_direct_route_for_host(
|
||||
if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route_src)
|
||||
|| _data_get_direct_route_for_host(
|
||||
self,
|
||||
addr_family,
|
||||
p_gateway,
|
||||
|
|
@ -2456,6 +2517,7 @@ nm_l3_config_data_add_dependent_device_routes(NML3ConfigData * self,
|
|||
.network = *a6,
|
||||
.plen = plen,
|
||||
};
|
||||
|
||||
nm_platform_ip_route_normalize(addr_family, &rx.rx);
|
||||
nm_l3_config_data_add_route(self, addr_family, NULL, &rx.rx);
|
||||
}
|
||||
|
|
@ -2844,6 +2906,7 @@ nm_l3_config_data_merge(NML3ConfigData * self,
|
|||
NML3ConfigMergeHookResult hook_result = {
|
||||
.ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
|
||||
.assume_config_once = NM_OPTION_BOOL_DEFAULT,
|
||||
.force_commit = NM_OPTION_BOOL_DEFAULT,
|
||||
};
|
||||
|
||||
#define _ensure_a() \
|
||||
|
|
@ -2882,6 +2945,12 @@ nm_l3_config_data_merge(NML3ConfigData * self,
|
|||
a.ax.a_assume_config_once = (!!hook_result.assume_config_once);
|
||||
}
|
||||
|
||||
if (hook_result.force_commit != NM_OPTION_BOOL_DEFAULT
|
||||
&& (!!hook_result.force_commit) != a_src->a_force_commit) {
|
||||
_ensure_a();
|
||||
a.ax.a_force_commit = (!!hook_result.force_commit);
|
||||
}
|
||||
|
||||
nm_l3_config_data_add_address_full(self,
|
||||
addr_family,
|
||||
a_src == &a.ax ? NULL : obj,
|
||||
|
|
@ -2902,6 +2971,7 @@ nm_l3_config_data_merge(NML3ConfigData * self,
|
|||
NML3ConfigMergeHookResult hook_result = {
|
||||
.ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
|
||||
.assume_config_once = NM_OPTION_BOOL_DEFAULT,
|
||||
.force_commit = NM_OPTION_BOOL_DEFAULT,
|
||||
};
|
||||
|
||||
#define _ensure_r() \
|
||||
|
|
@ -2933,6 +3003,12 @@ nm_l3_config_data_merge(NML3ConfigData * self,
|
|||
r.rx.r_assume_config_once = (!!hook_result.assume_config_once);
|
||||
}
|
||||
|
||||
if (hook_result.force_commit != NM_OPTION_BOOL_DEFAULT
|
||||
&& (!!hook_result.force_commit) != r_src->r_force_commit) {
|
||||
_ensure_r();
|
||||
r.rx.r_force_commit = (!!hook_result.force_commit);
|
||||
}
|
||||
|
||||
if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_CLONE)) {
|
||||
if (r_src->table_any) {
|
||||
_ensure_r();
|
||||
|
|
@ -3019,6 +3095,12 @@ 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;
|
||||
|
||||
if (self->ip6_token.id == 0)
|
||||
self->ip6_token.id = src->ip6_token.id;
|
||||
|
||||
self->metered = NM_MAX((NMTernary) self->metered, (NMTernary) src->metered);
|
||||
|
||||
if (self->proxy_method == NM_PROXY_CONFIG_METHOD_UNKNOWN)
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ NML3ConfigData *nm_l3_config_data_new_from_platform(NMDedupMultiIndex * mu
|
|||
typedef struct {
|
||||
NMOptionBool ip4acd_not_ready;
|
||||
NMOptionBool assume_config_once;
|
||||
NMOptionBool force_commit;
|
||||
} NML3ConfigMergeHookResult;
|
||||
|
||||
typedef gboolean (*NML3ConfigMergeHookAddObj)(const NML3ConfigData * l3cd,
|
||||
|
|
@ -446,6 +447,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);
|
||||
|
||||
|
|
@ -470,6 +476,10 @@ guint32 nm_l3_config_data_get_ip6_mtu(const NML3ConfigData *self);
|
|||
|
||||
gboolean nm_l3_config_data_set_ip6_mtu(NML3ConfigData *self, guint32 ip6_mtu);
|
||||
|
||||
NMUtilsIPv6IfaceId nm_l3_config_data_get_ip6_token(const NML3ConfigData *self);
|
||||
|
||||
gboolean nm_l3_config_data_set_ip6_token(NML3ConfigData *self, NMUtilsIPv6IfaceId ipv6_token);
|
||||
|
||||
const in_addr_t *nm_l3_config_data_get_wins(const NML3ConfigData *self, guint *out_len);
|
||||
|
||||
gboolean nm_l3_config_data_add_wins(NML3ConfigData *self, in_addr_t wins);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ struct _NML3IPv6LL {
|
|||
* with the configuration. */
|
||||
const NML3ConfigData *l3cd;
|
||||
|
||||
guint32 route_table;
|
||||
|
||||
/* "assume" means that we first look whether there is any suitable
|
||||
* IPv6 address on the device, and in that case, try to use that
|
||||
* instead of generating a new one. Otherwise, we always try to
|
||||
|
|
@ -410,7 +412,7 @@ _lladdr_handle_changed(NML3IPv6LL *self)
|
|||
l3cd,
|
||||
NM_L3CFG_CONFIG_PRIORITY_IPV6LL,
|
||||
0,
|
||||
0,
|
||||
self->route_table,
|
||||
NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4,
|
||||
NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6,
|
||||
0,
|
||||
|
|
@ -624,6 +626,7 @@ _nm_l3_ipv6ll_new(NML3Cfg * l3cfg,
|
|||
const char * ifname,
|
||||
const char * network_id,
|
||||
const NMUtilsIPv6IfaceId *token_iid,
|
||||
guint32 route_table,
|
||||
NML3IPv6LLNotifyFcn notify_fcn,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
|
@ -647,6 +650,7 @@ _nm_l3_ipv6ll_new(NML3Cfg * l3cfg,
|
|||
.cur_lladdr_obj = NULL,
|
||||
.cur_lladdr = IN6ADDR_ANY_INIT,
|
||||
.assume = assume,
|
||||
.route_table = route_table,
|
||||
.addrgen =
|
||||
{
|
||||
.stable_type = stable_type,
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ NML3IPv6LL *_nm_l3_ipv6ll_new(NML3Cfg * l3cfg,
|
|||
const char * ifname,
|
||||
const char * network_id,
|
||||
const NMUtilsIPv6IfaceId *token_iid,
|
||||
guint32 route_table,
|
||||
NML3IPv6LLNotifyFcn notify_fcn,
|
||||
gpointer user_data);
|
||||
|
||||
|
|
@ -57,6 +58,7 @@ nm_l3_ipv6ll_new_stable_privacy(NML3Cfg * l3cfg,
|
|||
NMUtilsStableType stable_type,
|
||||
const char * ifname,
|
||||
const char * network_id,
|
||||
guint32 route_table,
|
||||
NML3IPv6LLNotifyFcn notify_fcn,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
|
@ -67,6 +69,7 @@ nm_l3_ipv6ll_new_stable_privacy(NML3Cfg * l3cfg,
|
|||
ifname,
|
||||
network_id,
|
||||
NULL,
|
||||
route_table,
|
||||
notify_fcn,
|
||||
user_data);
|
||||
}
|
||||
|
|
@ -75,6 +78,7 @@ static inline NML3IPv6LL *
|
|||
nm_l3_ipv6ll_new_token(NML3Cfg * l3cfg,
|
||||
gboolean assume,
|
||||
const NMUtilsIPv6IfaceId *token_iid,
|
||||
guint32 route_table,
|
||||
NML3IPv6LLNotifyFcn notify_fcn,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
|
@ -84,6 +88,7 @@ nm_l3_ipv6ll_new_token(NML3Cfg * l3cfg,
|
|||
NULL,
|
||||
NULL,
|
||||
token_iid,
|
||||
route_table,
|
||||
notify_fcn,
|
||||
user_data);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue