ip: configurable address pool and lease time of DHCP server in shared mode

Introduce a new options to NMSettingIpConfig. When set, ipv4.shared-dhcp-range
and ipv4.shared-dhcp-lease-time can be passed to dnsmasq to allow configuration
of DHCP server address pool range and lease time.

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/941
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2028
This commit is contained in:
Roman Pavelka
2024-08-30 19:03:12 +02:00
committed by Lubomir Rintel
parent 0209a55d24
commit 38d1bcee3b
23 changed files with 1654 additions and 572 deletions

3
NEWS
View File

@@ -24,6 +24,9 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
name server is reached only via the device that specifies it. name server is reached only via the device that specifies it.
* Support OCI in nm-cloud-setup * Support OCI in nm-cloud-setup
* Added support for ethtool FEC mode * Added support for ethtool FEC mode
* Add new ipv4.shared-dhcp-range and ipv4.shared-dhcp-lease-time,
which allows you to customize the DHCP range and lease time offered
by DHCP server in `shared` connection method.
============================================= =============================================
NetworkManager-1.50 NetworkManager-1.50

View File

@@ -13542,6 +13542,9 @@ _dev_ipshared4_spawn_dnsmasq(NMDevice *self)
NMConnection *applied; NMConnection *applied;
gs_unref_array GArray *conflicts = NULL; gs_unref_array GArray *conflicts = NULL;
gboolean ready; gboolean ready;
NMSettingIPConfig *s_ip4 = NULL;
const char *shared_dhcp_range;
int shared_dhcp_lease_time;
nm_assert(priv->ipshared_data_4.v4.firewall_config); nm_assert(priv->ipshared_data_4.v4.firewall_config);
nm_assert(priv->ipshared_data_4.v4.dnsmasq_state_id == 0); nm_assert(priv->ipshared_data_4.v4.dnsmasq_state_id == 0);
@@ -13587,9 +13590,14 @@ _dev_ipshared4_spawn_dnsmasq(NMDevice *self)
break; break;
} }
s_ip4 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG);
shared_dhcp_range = nm_setting_ip_config_get_shared_dhcp_range(s_ip4);
shared_dhcp_lease_time = nm_setting_ip_config_get_shared_dhcp_lease_time(s_ip4);
priv->ipshared_data_4.v4.dnsmasq_manager = nm_dnsmasq_manager_new(ip_iface); priv->ipshared_data_4.v4.dnsmasq_manager = nm_dnsmasq_manager_new(ip_iface);
if (!nm_dnsmasq_manager_start(priv->ipshared_data_4.v4.dnsmasq_manager, if (!nm_dnsmasq_manager_start(priv->ipshared_data_4.v4.dnsmasq_manager,
priv->ipshared_data_4.v4.l3cd, priv->ipshared_data_4.v4.l3cd,
shared_dhcp_range,
shared_dhcp_lease_time,
announce_android_metered, announce_android_metered,
&error)) { &error)) {
_LOGW_ipshared(AF_INET, "could not start dnsmasq: %s", error->message); _LOGW_ipshared(AF_INET, "could not start dnsmasq: %s", error->message);

View File

@@ -92,6 +92,8 @@ static GPtrArray *
create_dm_cmd_line(const char *iface, create_dm_cmd_line(const char *iface,
const NML3ConfigData *l3cd, const NML3ConfigData *l3cd,
const char *pidfile, const char *pidfile,
const char *shared_dhcp_range,
int shared_dhcp_lease_time,
gboolean announce_android_metered, gboolean announce_android_metered,
GError **error) GError **error)
{ {
@@ -108,6 +110,10 @@ create_dm_cmd_line(const char *iface,
guint n; guint n;
guint i; guint i;
nm_assert((shared_dhcp_lease_time == 0) || (shared_dhcp_lease_time == G_MAXINT32)
|| ((NM_MIN_FINITE_LEASE_TIME <= shared_dhcp_lease_time)
&& (shared_dhcp_lease_time <= NM_MAX_FINITE_LEASE_TIME)));
listen_address = NMP_OBJECT_CAST_IP4_ADDRESS( listen_address = NMP_OBJECT_CAST_IP4_ADDRESS(
nm_l3_config_data_get_first_obj(l3cd, NMP_OBJECT_TYPE_IP4_ADDRESS, NULL)); nm_l3_config_data_get_first_obj(l3cd, NMP_OBJECT_TYPE_IP4_ADDRESS, NULL));
@@ -150,14 +156,32 @@ create_dm_cmd_line(const char *iface,
nm_strv_ptrarray_add_string_concat(cmd, "--listen-address=", listen_address_s); nm_strv_ptrarray_add_string_concat(cmd, "--listen-address=", listen_address_s);
if (!nm_dnsmasq_utils_get_range(listen_address, first, last, &error_desc)) { shared_dhcp_lease_time = (shared_dhcp_lease_time != 0) ? shared_dhcp_lease_time : 3600;
if (shared_dhcp_range && *shared_dhcp_range) {
if (shared_dhcp_lease_time < G_MAXINT32) {
nm_strv_ptrarray_add_string_printf(cmd,
"--dhcp-range=%s,%d",
shared_dhcp_range,
shared_dhcp_lease_time);
} else {
nm_strv_ptrarray_add_string_printf(cmd, "--dhcp-range=%s,infinite", shared_dhcp_range);
}
} else if (nm_dnsmasq_utils_get_range(listen_address, first, last, &error_desc)) {
if (shared_dhcp_lease_time < G_MAXINT32) {
nm_strv_ptrarray_add_string_printf(cmd,
"--dhcp-range=%s,%s,%d",
first,
last,
shared_dhcp_lease_time);
} else {
nm_strv_ptrarray_add_string_printf(cmd, "--dhcp-range=%s,%s,infinite", first, last);
}
} else {
g_set_error_literal(error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, error_desc); g_set_error_literal(error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, error_desc);
_LOGW("failed to find DHCP address ranges: %s", error_desc); _LOGW("failed to find DHCP address ranges: %s", error_desc);
return NULL; return NULL;
} }
nm_strv_ptrarray_add_string_printf(cmd, "--dhcp-range=%s,%s,60m", first, last);
if (nm_l3_config_data_get_best_default_route(l3cd, AF_INET)) { 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); nm_strv_ptrarray_add_string_concat(cmd, "--dhcp-option=option:router,", listen_address_s);
} }
@@ -249,6 +273,8 @@ out:
gboolean gboolean
nm_dnsmasq_manager_start(NMDnsMasqManager *manager, nm_dnsmasq_manager_start(NMDnsMasqManager *manager,
const NML3ConfigData *l3cd, const NML3ConfigData *l3cd,
const char *shared_dhcp_range,
int shared_dhcp_lease_time,
gboolean announce_android_metered, gboolean announce_android_metered,
GError **error) GError **error)
{ {
@@ -265,7 +291,13 @@ nm_dnsmasq_manager_start(NMDnsMasqManager *manager,
kill_existing_by_pidfile(priv->pidfile); kill_existing_by_pidfile(priv->pidfile);
dm_cmd = create_dm_cmd_line(priv->iface, l3cd, priv->pidfile, announce_android_metered, error); dm_cmd = create_dm_cmd_line(priv->iface,
l3cd,
priv->pidfile,
shared_dhcp_range,
shared_dhcp_lease_time,
announce_android_metered,
error);
if (!dm_cmd) if (!dm_cmd)
return FALSE; return FALSE;

View File

@@ -35,6 +35,8 @@ NMDnsMasqManager *nm_dnsmasq_manager_new(const char *iface);
gboolean nm_dnsmasq_manager_start(NMDnsMasqManager *manager, gboolean nm_dnsmasq_manager_start(NMDnsMasqManager *manager,
const NML3ConfigData *l3cd, const NML3ConfigData *l3cd,
const char *shared_dhcp_range,
int shared_dhcp_lease_time,
gboolean announce_android_metered, gboolean announce_android_metered,
GError **error); GError **error);

View File

@@ -2019,6 +2019,8 @@ global:
nm_setting_ip4_config_get_dhcp_ipv6_only_preferred; nm_setting_ip4_config_get_dhcp_ipv6_only_preferred;
nm_setting_ip4_dhcp_ipv6_only_preferred_get_type; nm_setting_ip4_dhcp_ipv6_only_preferred_get_type;
nm_setting_ip_config_get_routed_dns; nm_setting_ip_config_get_routed_dns;
nm_setting_ip_config_get_shared_dhcp_range;
nm_setting_ip_config_get_shared_dhcp_lease_time;
nm_setting_ip_config_routed_dns_get_type; nm_setting_ip_config_routed_dns_get_type;
nm_setting_ipvlan_get_mode; nm_setting_ipvlan_get_mode;
nm_setting_ipvlan_get_parent; nm_setting_ipvlan_get_parent;

View File

@@ -1,4 +1,5 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
libnm_core_aux_intern_inc = include_directories('.')
libnm_core_aux_intern = static_library( libnm_core_aux_intern = static_library(
'nm-core-aux-intern', 'nm-core-aux-intern',

View File

@@ -478,6 +478,150 @@ nm_utils_validate_dhcp_dscp(const char *dscp, GError **error)
return TRUE; return TRUE;
} }
gboolean
nm_utils_validate_shared_dhcp_range(const char *shared_dhcp_range,
GPtrArray *addresses,
GError **error)
{
char *start_address_str;
char *end_address_str;
NMIPAddress *interface_address_with_prefix;
NMIPAddr interface_address;
NMIPAddr start_address;
NMIPAddr end_address;
guint32 i;
guint32 mask;
guint32 prefix_length;
guint32 start_network;
guint32 end_network;
guint32 interface_network;
guint32 start_ip_length;
bool range_is_in_interface_network;
g_return_val_if_fail(!error || !(*error), FALSE);
if (!shared_dhcp_range) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("NULL DHCP range; it should be provided as <START_IP>,<END_IP>."));
return FALSE;
}
if (!*shared_dhcp_range) {
return TRUE;
}
if (!addresses) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("Non-NULL range and NULL addresses detected."));
return FALSE;
}
end_address_str = strchr(shared_dhcp_range, ',');
if (!end_address_str) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("Invalid DHCP range; it should be provided as <START_IP>,<END_IP>."));
return FALSE;
}
start_ip_length = end_address_str - shared_dhcp_range;
if (start_ip_length > 15) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("Start IP has invalid length."));
return FALSE;
}
start_address_str = strndupa(shared_dhcp_range, start_ip_length);
++end_address_str; /* end address is pointing to ',', shift it to the actual address */
if (!nm_inet_parse_bin(AF_INET, start_address_str, NULL, &start_address)) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("Start IP is invalid."));
return FALSE;
}
if (!nm_inet_parse_bin(AF_INET, end_address_str, NULL, &end_address)) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("End IP is invalid."));
return FALSE;
}
if (ntohl(start_address.addr4) > ntohl(end_address.addr4)) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("Start IP should be lower than the end IP."));
return FALSE;
}
range_is_in_interface_network = FALSE;
for (i = 0; i < (*addresses).len; ++i) {
interface_address_with_prefix = (NMIPAddress *) addresses->pdata[i];
nm_inet_parse_bin(AF_INET,
nm_ip_address_get_address(interface_address_with_prefix),
NULL,
&interface_address);
prefix_length = nm_ip_address_get_prefix(interface_address_with_prefix);
mask = nm_utils_ip4_prefix_to_netmask(prefix_length);
interface_network = interface_address.addr4 & mask;
start_network = start_address.addr4 & mask;
end_network = end_address.addr4 & mask;
if (start_network == interface_network && end_network == interface_network) {
range_is_in_interface_network = TRUE;
break;
}
}
if (!range_is_in_interface_network) {
g_set_error_literal(
error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("Requested range is not in any network configured on the interface."));
return FALSE;
}
return TRUE;
}
gboolean
nm_utils_validate_shared_dhcp_lease_time(int shared_dhcp_lease_time, GError **error)
{
g_return_val_if_fail(!error || !(*error), FALSE);
if (shared_dhcp_lease_time == 0 || shared_dhcp_lease_time == G_MAXINT32) {
return TRUE;
}
if (shared_dhcp_lease_time < NM_MIN_FINITE_LEASE_TIME
|| NM_MAX_FINITE_LEASE_TIME < shared_dhcp_lease_time) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("Invalid DHCP lease time value; it should be either default or a positive "
"number between %u and %u or %s."),
NM_MIN_FINITE_LEASE_TIME,
NM_MAX_FINITE_LEASE_TIME,
NM_INFINITE_LEASE_TIME);
return FALSE;
}
return TRUE;
}
gboolean gboolean
nm_settings_connection_validate_permission_user(const char *item, gssize len) nm_settings_connection_validate_permission_user(const char *item, gssize len)
{ {

View File

@@ -277,6 +277,17 @@ gboolean nm_utils_validate_dhcp_dscp(const char *dscp, GError **error);
/*****************************************************************************/ /*****************************************************************************/
#define NM_MIN_FINITE_LEASE_TIME 120
#define NM_MAX_FINITE_LEASE_TIME (3600 * 24 * 365)
#define NM_INFINITE_LEASE_TIME "infinity"
gboolean nm_utils_validate_shared_dhcp_range(const char *shared_dhcp_range,
GPtrArray *addresses,
GError **error);
gboolean nm_utils_validate_shared_dhcp_lease_time(int shared_dhcp_lease_time, GError **error);
/*****************************************************************************/
#define NM_SETTINGS_CONNECTION_PERMISSION_USER "user" #define NM_SETTINGS_CONNECTION_PERMISSION_USER "user"
#define NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX "user:" #define NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX "user:"

View File

@@ -0,0 +1,34 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
exe = executable(
'test-libnm-core-utils',
'test-libnm-core-utils.c',
include_directories: [
libnm_core_aux_intern_inc
],
link_with: [
libnm_core_aux_intern,
libnm_core_impl,
libnm_base,
libnm_crypto,
libnm_systemd_shared,
libnm_log_null,
libnm_glib_aux,
libnm_std_aux,
libc_siphash,
],
dependencies: [
libnm_client_public_dep,
libnm_core_public_dep,
uuid_dep,
glib_dep,
dl_dep,
],
)
test(
'src/libnm-core-aux-intern/tests/test-libnm-core-utils',
exe,
args: test_args + [exe.full_path()],
timeout: default_test_timeout,
)

View File

@@ -0,0 +1,364 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2024 Advantech Czech s.r.o.
*/
#include "libnm-glib-aux/nm-default-glib-i18n-prog.h"
#include "libnm-glib-aux/nm-test-utils.h"
#include "nm-libnm-core-utils.h"
#include "nm-errors.h"
static void
empty_range_valid_for_null_addresses(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_range("", addresses, &error);
g_assert(result);
g_assert_null(error);
}
static void
empty_range_valid_for_empty_addresses(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
result = nm_utils_validate_shared_dhcp_range("", addresses, &error);
g_assert(result);
g_assert_null(error);
}
static void
valid_range_for_single_address(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL));
result = nm_utils_validate_shared_dhcp_range("192.168.0.2,192.168.0.254", addresses, &error);
g_assert(result);
g_assert_null(error);
}
static void
valid_range_for_second_address(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, &error));
g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.1.254", 24, &error));
result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.254", addresses, &error);
g_assert(result);
g_assert_null(error);
}
static void
invalid_null_range_for_null_addresses(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_range(NULL, addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
invalid_null_range_for_empty_addresses(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.254", addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
any_range_invalid_for_null_addresses(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.254", addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
any_range_invalid_for_empty_addresses(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.254", addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
invalid_range_xyz(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL));
result = nm_utils_validate_shared_dhcp_range("xyz", addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
invalid_range_single_comma(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL));
result = nm_utils_validate_shared_dhcp_range(",", addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
invalid_first_address_of_range(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL));
result = nm_utils_validate_shared_dhcp_range("xyz,192.168.0.100", addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
invalid_second_address_of_range(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL));
result = nm_utils_validate_shared_dhcp_range("192.168.0.100,xyz", addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
invalid_inverted_range(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL));
result = nm_utils_validate_shared_dhcp_range("192.168.0.200,192.168.0.100", addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
invalid_range_outside_address_space(void)
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_free_error GError *error = NULL;
gboolean result;
addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
g_ptr_array_add(addresses, nm_ip_address_new(AF_INET, "192.168.0.1", 24, NULL));
result = nm_utils_validate_shared_dhcp_range("192.168.1.2,192.168.1.100", addresses, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
/*****************************************************************************/
static void
valid_zero_lease_time(void)
{
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_lease_time(0, &error);
g_assert(result);
g_assert_null(error);
}
static void
minimal_valid_lease_time(void)
{
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_lease_time(NM_MIN_FINITE_LEASE_TIME, &error);
g_assert(result);
g_assert_null(error);
}
static void
middle_valid_lease_time(void)
{
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_lease_time(
(NM_MIN_FINITE_LEASE_TIME + NM_MAX_FINITE_LEASE_TIME) / 2,
&error);
g_assert(result);
g_assert_null(error);
}
static void
maximal_valid_lease_time(void)
{
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_lease_time(NM_MAX_FINITE_LEASE_TIME, &error);
g_assert(result);
g_assert_null(error);
}
static void
infinite_lease_time(void)
{
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_lease_time(G_MAXINT32, &error);
g_assert(result);
g_assert_null(error);
}
static void
too_small_lease_time(void)
{
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_lease_time(1, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
static void
too_large_lease_time(void)
{
gs_free_error GError *error = NULL;
gboolean result;
result = nm_utils_validate_shared_dhcp_lease_time(NM_MAX_FINITE_LEASE_TIME + 1, &error);
g_assert_false(result);
g_assert_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
}
/*****************************************************************************/
NMTST_DEFINE();
int
main(int argc, char **argv)
{
nmtst_init(&argc, &argv, TRUE);
g_test_add_func("/core/utils/shared_dhcp_range/empty_range_valid_for_null_addresses",
empty_range_valid_for_null_addresses);
g_test_add_func("/core/utils/shared_dhcp_range/empty_range_valid_for_empty_addresses",
empty_range_valid_for_empty_addresses);
g_test_add_func("/core/utils/shared_dhcp_range/valid_range_for_single_address",
valid_range_for_single_address);
g_test_add_func("/core/utils/shared_dhcp_range/valid_range_for_second_address",
valid_range_for_second_address);
g_test_add_func("/core/utils/shared_dhcp_range/invalid_null_range_for_null_addresses",
invalid_null_range_for_null_addresses);
g_test_add_func("/core/utils/shared_dhcp_range/invalid_null_range_for_empty_addresses",
invalid_null_range_for_empty_addresses);
g_test_add_func("/core/utils/shared_dhcp_range/any_range_invalid_for_null_addresses",
any_range_invalid_for_null_addresses);
g_test_add_func("/core/utils/shared_dhcp_range/any_range_invalid_for_empty_addresses",
any_range_invalid_for_empty_addresses);
g_test_add_func("/core/utils/shared_dhcp_range/invalid_range_xyz", invalid_range_xyz);
g_test_add_func("/core/utils/shared_dhcp_range/invalid_range_single_comma",
invalid_range_single_comma);
g_test_add_func("/core/utils/shared_dhcp_range/invalid_first_address_of_range",
invalid_first_address_of_range);
g_test_add_func("/core/utils/shared_dhcp_range/invalid_second_address_of_range",
invalid_second_address_of_range);
g_test_add_func("/core/utils/shared_dhcp_range/invalid_inverted_range", invalid_inverted_range);
g_test_add_func("/core/utils/shared_dhcp_range/invalid_range_outside_address_space",
invalid_range_outside_address_space);
g_test_add_func("/core/utils/shared_dhcp_lease_time/valid_zero_lease_time",
valid_zero_lease_time);
g_test_add_func("/core/utils/shared_dhcp_lease_time/minimal_valid_lease_time",
minimal_valid_lease_time);
g_test_add_func("/core/utils/shared_dhcp_lease_time/middle_valid_lease_time",
middle_valid_lease_time);
g_test_add_func("/core/utils/shared_dhcp_lease_time/maximal_valid_lease_time",
maximal_valid_lease_time);
g_test_add_func("/core/utils/shared_dhcp_lease_time/infinite_lease_time", infinite_lease_time);
g_test_add_func("/core/utils/shared_dhcp_lease_time/too_small_lease_time",
too_small_lease_time);
g_test_add_func("/core/utils/shared_dhcp_lease_time/too_large_lease_time",
too_large_lease_time);
return g_test_run();
}

View File

@@ -1771,6 +1771,14 @@
<property name="routing-rules" <property name="routing-rules"
dbus-type="aa{sv}" dbus-type="aa{sv}"
/> />
<property name="shared-dhcp-lease-time"
dbus-type="i"
gprop-type="gint"
/>
<property name="shared-dhcp-range"
dbus-type="s"
gprop-type="gchararray"
/>
</setting> </setting>
<setting name="ipv6" <setting name="ipv6"
gtype="NMSettingIP6Config" gtype="NMSettingIP6Config"
@@ -1926,6 +1934,14 @@
<property name="routing-rules" <property name="routing-rules"
dbus-type="aa{sv}" dbus-type="aa{sv}"
/> />
<property name="shared-dhcp-lease-time"
dbus-type="i"
gprop-type="gint"
/>
<property name="shared-dhcp-range"
dbus-type="s"
gprop-type="gchararray"
/>
<property name="temp-preferred-lifetime" <property name="temp-preferred-lifetime"
dbus-type="i" dbus-type="i"
gprop-type="gint" gprop-type="gint"

View File

@@ -4007,7 +4007,9 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMSettingIPConfig,
PROP_AUTO_ROUTE_EXT_GW, PROP_AUTO_ROUTE_EXT_GW,
PROP_REPLACE_LOCAL_RULE, PROP_REPLACE_LOCAL_RULE,
PROP_DHCP_SEND_RELEASE, PROP_DHCP_SEND_RELEASE,
PROP_ROUTED_DNS, ); PROP_ROUTED_DNS,
PROP_SHARED_DHCP_RANGE,
PROP_SHARED_DHCP_LEASE_TIME, );
G_DEFINE_ABSTRACT_TYPE(NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING) G_DEFINE_ABSTRACT_TYPE(NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING)
@@ -5519,6 +5521,44 @@ nm_setting_ip_config_get_routed_dns(NMSettingIPConfig *setting)
return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->routed_dns; return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->routed_dns;
} }
/**
* nm_setting_ip_config_get_shared_dhcp_range:
* @setting: the #NMSettingIPConfig
*
* Returns the value contained in the #NMSettingIPConfig:shared-dhcp-range
* property.
*
* Returns: the configured DHCP server range
*
* Since: 1.52
**/
const char *
nm_setting_ip_config_get_shared_dhcp_range(NMSettingIPConfig *setting)
{
g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL);
return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->shared_dhcp_range;
}
/**
* nm_setting_ip_config_get_shared_dhcp_lease_time:
* @setting: the #NMSettingIPConfig
*
* Returns the value contained in the #NMSettingIPConfig:shared-dhcp-lease-time
* property.
*
* Returns: the configured DHCP server lease time
*
* Since: 1.52
**/
int
nm_setting_ip_config_get_shared_dhcp_lease_time(NMSettingIPConfig *setting)
{
g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0);
return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->shared_dhcp_lease_time;
}
static gboolean static gboolean
verify_label(const char *label) verify_label(const char *label)
{ {
@@ -5815,6 +5855,26 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
return FALSE; return FALSE;
} }
/* Validate DHCP range served in the shared mode */
if (priv->shared_dhcp_range
&& !nm_utils_validate_shared_dhcp_range(priv->shared_dhcp_range, priv->addresses, error)) {
g_prefix_error(error,
"%s.%s: ",
nm_setting_get_name(setting),
NM_SETTING_IP_CONFIG_SHARED_DHCP_RANGE);
return FALSE;
}
/* Validate DHCP lease time */
if (priv->shared_dhcp_lease_time
&& !nm_utils_validate_shared_dhcp_lease_time(priv->shared_dhcp_lease_time, error)) {
g_prefix_error(error,
"%s.%s: ",
nm_setting_get_name(setting),
NM_SETTING_IP_CONFIG_SHARED_DHCP_LEASE_TIME);
return FALSE;
}
/* Normalizable errors */ /* Normalizable errors */
if (priv->gateway && priv->never_default) { if (priv->gateway && priv->never_default) {
g_set_error(error, g_set_error(error,
@@ -6266,6 +6326,21 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family)
.direct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, routed_dns), .direct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, routed_dns),
.direct_data.enum_gtype = NM_TYPE_SETTING_IP_CONFIG_ROUTED_DNS); .direct_data.enum_gtype = NM_TYPE_SETTING_IP_CONFIG_ROUTED_DNS);
_nm_properties_override_gobj(
properties_override,
obj_properties[PROP_SHARED_DHCP_RANGE],
&nm_sett_info_propert_type_direct_string,
.direct_offset =
NM_STRUCT_OFFSET_ENSURE_TYPE(char *, NMSettingIPConfigPrivate, shared_dhcp_range),
.direct_string_allow_empty = TRUE);
_nm_properties_override_gobj(
properties_override,
obj_properties[PROP_SHARED_DHCP_LEASE_TIME],
&nm_sett_info_propert_type_direct_int32,
.direct_offset =
NM_STRUCT_OFFSET_ENSURE_TYPE(gint32, NMSettingIPConfigPrivate, shared_dhcp_lease_time));
return properties_override; return properties_override;
} }
@@ -7086,5 +7161,48 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass)
NM_TERNARY_DEFAULT, NM_TERNARY_DEFAULT,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* NMSettingIPConfig:shared-dhcp-range:
*
* This option allows you to specify a custom DHCP range for the shared connection
* method. The value is expected to be in `<START_ADDRESS>,<END_ADDRESS>` format.
* The range should be part of network set by ipv4.address option and it should
* not contain network address or broadcast address. If this option is not specified,
* the DHCP range will be automatically determined based on the interface address.
* The range will be selected to be adjacent to the interface address, either before
* or after it, with the larger possible range being preferred. The range will be
* adjusted to fill the available address space, except for networks with a prefix
* length greater than 24, which will be treated as if they have a prefix length of 24.
*
* Since: 1.52
*/
obj_properties[PROP_SHARED_DHCP_RANGE] =
g_param_spec_string(NM_SETTING_IP_CONFIG_SHARED_DHCP_RANGE,
"",
"",
NULL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* NMSettingIPConfig:shared-dhcp-lease-time:
*
* This option allows you to specify a custom DHCP lease time for the shared connection
* method in seconds. The value should be either a number between 120 and 31536000 (one year)
* If this option is not specified, 3600 (one hour) is used.
*
* Special values are 0 for default value of 1 hour and 2147483647 (MAXINT32) for infinite lease time.
*
* Since: 1.52
*/
obj_properties[PROP_SHARED_DHCP_LEASE_TIME] =
g_param_spec_int(NM_SETTING_IP_CONFIG_SHARED_DHCP_LEASE_TIME,
"",
"",
0,
G_MAXINT32,
0,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | NM_SETTING_PARAM_FUZZY_IGNORE
| 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, obj_properties);
} }

View File

@@ -440,6 +440,30 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
return FALSE; return FALSE;
} }
if (nm_setting_ip_config_get_shared_dhcp_range(s_ip)) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("Shared DHCP range is not supported for IPv6"));
g_prefix_error(error,
"%s.%s: ",
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP_CONFIG_SHARED_DHCP_RANGE);
return FALSE;
}
if (nm_setting_ip_config_get_shared_dhcp_lease_time(s_ip)) {
g_set_error_literal(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("Shared DHCP lease time is not supported for IPv6"));
g_prefix_error(error,
"%s.%s: ",
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP_CONFIG_SHARED_DHCP_LEASE_TIME);
return FALSE;
}
/* Failures from here on, are NORMALIZABLE_ERROR... */ /* Failures from here on, are NORMALIZABLE_ERROR... */
if (token_needs_normalization) { if (token_needs_normalization) {

View File

@@ -186,6 +186,8 @@ typedef struct {
char *dhcp_hostname; char *dhcp_hostname;
char *dhcp_iaid; char *dhcp_iaid;
char *dhcp_dscp; char *dhcp_dscp;
char *shared_dhcp_range;
int shared_dhcp_lease_time;
gint64 route_metric; gint64 route_metric;
int auto_route_ext_gw; int auto_route_ext_gw;
int replace_local_rule; int replace_local_rule;

View File

@@ -3962,7 +3962,7 @@ typedef struct {
typedef struct { typedef struct {
const char *name; const char *name;
DiffKey keys[40]; DiffKey keys[41];
} DiffSetting; } DiffSetting;
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
@@ -4097,6 +4097,8 @@ test_connection_diff_a_only(void)
{NM_SETTING_IP_CONFIG_REPLACE_LOCAL_RULE, NM_SETTING_DIFF_RESULT_IN_A}, {NM_SETTING_IP_CONFIG_REPLACE_LOCAL_RULE, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_DHCP_SEND_RELEASE, NM_SETTING_DIFF_RESULT_IN_A}, {NM_SETTING_IP_CONFIG_DHCP_SEND_RELEASE, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_ROUTED_DNS, NM_SETTING_DIFF_RESULT_IN_A}, {NM_SETTING_IP_CONFIG_ROUTED_DNS, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_SHARED_DHCP_RANGE, NM_SETTING_DIFF_RESULT_IN_A},
{NM_SETTING_IP_CONFIG_SHARED_DHCP_LEASE_TIME, NM_SETTING_DIFF_RESULT_IN_A},
{NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN},
}}, }},
}; };

View File

@@ -362,6 +362,8 @@ char *nm_ip_routing_rule_to_string(const NMIPRoutingRule *self,
#define NM_SETTING_IP_CONFIG_REPLACE_LOCAL_RULE "replace-local-rule" #define NM_SETTING_IP_CONFIG_REPLACE_LOCAL_RULE "replace-local-rule"
#define NM_SETTING_IP_CONFIG_DHCP_SEND_RELEASE "dhcp-send-release" #define NM_SETTING_IP_CONFIG_DHCP_SEND_RELEASE "dhcp-send-release"
#define NM_SETTING_IP_CONFIG_ROUTED_DNS "routed-dns" #define NM_SETTING_IP_CONFIG_ROUTED_DNS "routed-dns"
#define NM_SETTING_IP_CONFIG_SHARED_DHCP_RANGE "shared-dhcp-range"
#define NM_SETTING_IP_CONFIG_SHARED_DHCP_LEASE_TIME "shared-dhcp-lease-time"
/* these are not real GObject properties. */ /* these are not real GObject properties. */
#define NM_SETTING_IP_CONFIG_ROUTING_RULES "routing-rules" #define NM_SETTING_IP_CONFIG_ROUTING_RULES "routing-rules"
@@ -536,6 +538,10 @@ NM_AVAILABLE_IN_1_52
NMSettingIPConfigRoutedDns nm_setting_ip_config_get_routed_dns(NMSettingIPConfig *setting); NMSettingIPConfigRoutedDns nm_setting_ip_config_get_routed_dns(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_52 NM_AVAILABLE_IN_1_52
NMTernary nm_setting_ip_config_get_dhcp_send_hostname_v2(NMSettingIPConfig *setting); NMTernary nm_setting_ip_config_get_dhcp_send_hostname_v2(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_52
const char *nm_setting_ip_config_get_shared_dhcp_range(NMSettingIPConfig *setting);
NM_AVAILABLE_IN_1_52
int nm_setting_ip_config_get_shared_dhcp_lease_time(NMSettingIPConfig *setting);
G_END_DECLS G_END_DECLS

View File

@@ -83,6 +83,8 @@
/*****************************************************************************/ /*****************************************************************************/
/* Reason for double application is described here
* https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html */
#define NM_STRINGIFY_ARG(contents) #contents #define NM_STRINGIFY_ARG(contents) #contents
#define NM_STRINGIFY(macro_or_string) NM_STRINGIFY_ARG(macro_or_string) #define NM_STRINGIFY(macro_or_string) NM_STRINGIFY_ARG(macro_or_string)

View File

@@ -6554,6 +6554,24 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = {
PROPERTY_INFO (NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_AUTO_ROUTE_EXT_GW, PROPERTY_INFO (NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_AUTO_ROUTE_EXT_GW,
.property_type = &_pt_gobject_ternary, .property_type = &_pt_gobject_ternary,
), ),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_SHARED_DHCP_RANGE, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_SHARED_DHCP_RANGE,
.property_type = &_pt_gobject_string,
),
PROPERTY_INFO (NM_SETTING_IP_CONFIG_SHARED_DHCP_LEASE_TIME, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_SHARED_DHCP_LEASE_TIME,
.property_type = &_pt_gobject_int,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
.value_infos = INT_VALUE_INFOS (
{
.value.i64 = 0,
.nick = "default",
},
{
.value.i64 = G_MAXINT32,
.nick = "infinity",
},
),
),
),
NULL NULL
}; };

View File

@@ -214,6 +214,8 @@
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTED_DNS N_("Whether to add routes for DNS servers. When enabled, NetworkManager adds a route for each DNS server that is associated with this connection either statically (defined in the connection profile) or dynamically (for example, retrieved via DHCP). The route guarantees that the DNS server is reached via this interface. When set to \"default\" (-1), the value from global configuration is used; if no global default is defined, this feature is disabled.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTED_DNS N_("Whether to add routes for DNS servers. When enabled, NetworkManager adds a route for each DNS server that is associated with this connection either statically (defined in the connection profile) or dynamically (for example, retrieved via DHCP). The route guarantees that the DNS server is reached via this interface. When set to \"default\" (-1), the value from global configuration is used; if no global default is defined, this feature is disabled.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTES N_("A list of IPv4 destination addresses, prefix length, optional IPv4 next hop addresses, optional route metric, optional attribute. The valid syntax is: \"ip[/prefix] [next-hop] [metric] [attribute=val]...[,ip[/prefix]...]\". For example \"192.0.2.0/24 10.1.1.1 77, 198.51.100.0/24\".") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTES N_("A list of IPv4 destination addresses, prefix length, optional IPv4 next hop addresses, optional route metric, optional attribute. The valid syntax is: \"ip[/prefix] [next-hop] [metric] [attribute=val]...[,ip[/prefix]...]\". For example \"192.0.2.0/24 10.1.1.1 77, 198.51.100.0/24\".")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTING_RULES N_("A comma separated list of routing rules for policy routing.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTING_RULES N_("A comma separated list of routing rules for policy routing.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_SHARED_DHCP_LEASE_TIME N_("This option allows you to specify a custom DHCP lease time for the shared connection method in seconds. The value should be either a number between 120 and 31536000 (one year) If this option is not specified, 3600 (one hour) is used. Special values are 0 for default value of 1 hour and 2147483647 (MAXINT32) for infinite lease time.")
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_SHARED_DHCP_RANGE N_("This option allows you to specify a custom DHCP range for the shared connection method. The value is expected to be in `<START_ADDRESS>,<END_ADDRESS>` format. The range should be part of network set by ipv4.address option and it should not contain network address or broadcast address. If this option is not specified, the DHCP range will be automatically determined based on the interface address. The range will be selected to be adjacent to the interface address, either before or after it, with the larger possible range being preferred. The range will be adjusted to fill the available address space, except for networks with a prefix length greater than 24, which will be treated as if they have a prefix length of 24.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE N_("Configure method for creating the IPv6 interface identifier of addresses with RFC4862 IPv6 Stateless Address Autoconfiguration and Link Local addresses. The permitted values are: \"eui64\" (0), \"stable-privacy\" (1), \"default\" (3) or \"default-or-eui64\" (2). If the property is set to \"eui64\", the addresses will be generated using the interface token derived from hardware address. This makes the host part of the address to stay constant, making it possible to track the host's presence when it changes networks. The address changes when the interface hardware is replaced. If a duplicate address is detected, there is also no fallback to generate another address. When configured, the \"ipv6.token\" is used instead of the MAC address to generate addresses for stateless autoconfiguration. If the property is set to \"stable-privacy\", the interface identifier is generated as specified by RFC7217. This works by hashing a host specific key (see NetworkManager(8) manual), the interface name, the connection's \"connection.stable-id\" property and the address prefix. This improves privacy by making it harder to use the address to track the host's presence and the address is stable when the network interface hardware is replaced. The special values \"default\" and \"default-or-eui64\" will fallback to the global connection default as documented in the NetworkManager.conf(5) manual. If the global default is not specified, the fallback value is \"stable-privacy\" or \"eui64\", respectively. If not specified, when creating a new profile the default is \"default\". Note that this setting is distinct from the Privacy Extensions as configured by \"ip6-privacy\" property and it does not affect the temporary addresses configured with this option.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE N_("Configure method for creating the IPv6 interface identifier of addresses with RFC4862 IPv6 Stateless Address Autoconfiguration and Link Local addresses. The permitted values are: \"eui64\" (0), \"stable-privacy\" (1), \"default\" (3) or \"default-or-eui64\" (2). If the property is set to \"eui64\", the addresses will be generated using the interface token derived from hardware address. This makes the host part of the address to stay constant, making it possible to track the host's presence when it changes networks. The address changes when the interface hardware is replaced. If a duplicate address is detected, there is also no fallback to generate another address. When configured, the \"ipv6.token\" is used instead of the MAC address to generate addresses for stateless autoconfiguration. If the property is set to \"stable-privacy\", the interface identifier is generated as specified by RFC7217. This works by hashing a host specific key (see NetworkManager(8) manual), the interface name, the connection's \"connection.stable-id\" property and the address prefix. This improves privacy by making it harder to use the address to track the host's presence and the address is stable when the network interface hardware is replaced. The special values \"default\" and \"default-or-eui64\" will fallback to the global connection default as documented in the NetworkManager.conf(5) manual. If the global default is not specified, the fallback value is \"stable-privacy\" or \"eui64\", respectively. If not specified, when creating a new profile the default is \"default\". Note that this setting is distinct from the Privacy Extensions as configured by \"ip6-privacy\" property and it does not affect the temporary addresses configured with this option.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDRESSES N_("A list of IPv6 addresses and their prefix length. Multiple addresses can be separated by comma. For example \"2001:db8:85a3::8a2e:370:7334/64, 2001:db8:85a3::5/64\". The addresses are listed in decreasing priority, meaning the first address will be the primary address. This can make a difference with IPv6 source address selection (RFC 6724, section 5).") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDRESSES N_("A list of IPv6 addresses and their prefix length. Multiple addresses can be separated by comma. For example \"2001:db8:85a3::8a2e:370:7334/64, 2001:db8:85a3::5/64\". The addresses are listed in decreasing priority, meaning the first address will be the primary address. This can make a difference with IPv6 source address selection (RFC 6724, section 5).")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_AUTO_ROUTE_EXT_GW N_("VPN connections will default to add the route automatically unless this setting is set to FALSE. For other connection types, adding such an automatic route is currently not supported and setting this to TRUE has no effect.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_AUTO_ROUTE_EXT_GW N_("VPN connections will default to add the route automatically unless this setting is set to FALSE. For other connection types, adding such an automatic route is currently not supported and setting this to TRUE has no effect.")
@@ -249,6 +251,8 @@
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTED_DNS N_("Whether to add routes for DNS servers. When enabled, NetworkManager adds a route for each DNS server that is associated with this connection either statically (defined in the connection profile) or dynamically (for example, retrieved via DHCP). The route guarantees that the DNS server is reached via this interface. When set to \"default\" (-1), the value from global configuration is used; if no global default is defined, this feature is disabled.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTED_DNS N_("Whether to add routes for DNS servers. When enabled, NetworkManager adds a route for each DNS server that is associated with this connection either statically (defined in the connection profile) or dynamically (for example, retrieved via DHCP). The route guarantees that the DNS server is reached via this interface. When set to \"default\" (-1), the value from global configuration is used; if no global default is defined, this feature is disabled.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTES N_("Array of IP routes.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTES N_("Array of IP routes.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTING_RULES N_("A comma separated list of routing rules for policy routing.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTING_RULES N_("A comma separated list of routing rules for policy routing.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_SHARED_DHCP_LEASE_TIME N_("This option allows you to specify a custom DHCP lease time for the shared connection method in seconds. The value should be either a number between 120 and 31536000 (one year) If this option is not specified, 3600 (one hour) is used. Special values are 0 for default value of 1 hour and 2147483647 (MAXINT32) for infinite lease time.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_SHARED_DHCP_RANGE N_("This option allows you to specify a custom DHCP range for the shared connection method. The value is expected to be in `<START_ADDRESS>,<END_ADDRESS>` format. The range should be part of network set by ipv4.address option and it should not contain network address or broadcast address. If this option is not specified, the DHCP range will be automatically determined based on the interface address. The range will be selected to be adjacent to the interface address, either before or after it, with the larger possible range being preferred. The range will be adjusted to fill the available address space, except for networks with a prefix length greater than 24, which will be treated as if they have a prefix length of 24.")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_TEMP_PREFERRED_LIFETIME N_("The preferred lifetime of autogenerated temporary addresses, in seconds. Having a per-connection setting set to \"0\" (default) means fallback to global configuration \"ipv6.temp-preferred-lifetime\" setting\". If it's also unspecified or set to \"0\", fallback to read \"/proc/sys/net/ipv6/conf/default/temp_prefered_lft\".") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_TEMP_PREFERRED_LIFETIME N_("The preferred lifetime of autogenerated temporary addresses, in seconds. Having a per-connection setting set to \"0\" (default) means fallback to global configuration \"ipv6.temp-preferred-lifetime\" setting\". If it's also unspecified or set to \"0\", fallback to read \"/proc/sys/net/ipv6/conf/default/temp_prefered_lft\".")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_TEMP_VALID_LIFETIME N_("The valid lifetime of autogenerated temporary addresses, in seconds. Having a per-connection setting set to \"0\" (default) means fallback to global configuration \"ipv6.temp-valid-lifetime\" setting\". If it's also unspecified or set to \"0\", fallback to read \"/proc/sys/net/ipv6/conf/default/temp_valid_lft\".") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_TEMP_VALID_LIFETIME N_("The valid lifetime of autogenerated temporary addresses, in seconds. Having a per-connection setting set to \"0\" (default) means fallback to global configuration \"ipv6.temp-valid-lifetime\" setting\". If it's also unspecified or set to \"0\", fallback to read \"/proc/sys/net/ipv6/conf/default/temp_valid_lft\".")
#define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_TOKEN N_("Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode. When set, the token is used as IPv6 interface identifier instead of the hardware address. This only applies to addresses from stateless autoconfiguration, not to IPv6 link local addresses.") #define DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_TOKEN N_("Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode. When set, the token is used as IPv6 interface identifier instead of the hardware address. This only applies to addresses from stateless autoconfiguration, not to IPv6 link local addresses.")

View File

@@ -120,6 +120,7 @@ if enable_tests
subdir('libnm-client-test') subdir('libnm-client-test')
subdir('libnm-glib-aux/tests') subdir('libnm-glib-aux/tests')
subdir('libnm-platform/tests') subdir('libnm-platform/tests')
subdir('libnm-core-aux-intern/tests')
subdir('libnm-core-impl/tests') subdir('libnm-core-impl/tests')
subdir('libnm-client-impl/tests') subdir('libnm-client-impl/tests')
subdir('libnm-client-aux-extern/tests') subdir('libnm-client-aux-extern/tests')

View File

@@ -1448,6 +1448,14 @@
nmcli-description="VPN connections will default to add the route automatically unless this setting is set to FALSE. For other connection types, adding such an automatic route is currently not supported and setting this to TRUE has no effect." nmcli-description="VPN connections will default to add the route automatically unless this setting is set to FALSE. For other connection types, adding such an automatic route is currently not supported and setting this to TRUE has no effect."
format="ternary" format="ternary"
values="true/yes/on, false/no/off, default/unknown" /> values="true/yes/on, false/no/off, default/unknown" />
<property name="shared-dhcp-range"
nmcli-description="This option allows you to specify a custom DHCP range for the shared connection method. The value is expected to be in `&lt;START_ADDRESS&gt;,&lt;END_ADDRESS&gt;` format. The range should be part of network set by ipv4.address option and it should not contain network address or broadcast address. If this option is not specified, the DHCP range will be automatically determined based on the interface address. The range will be selected to be adjacent to the interface address, either before or after it, with the larger possible range being preferred. The range will be adjusted to fill the available address space, except for networks with a prefix length greater than 24, which will be treated as if they have a prefix length of 24."
format="string" />
<property name="shared-dhcp-lease-time"
nmcli-description="This option allows you to specify a custom DHCP lease time for the shared connection method in seconds. The value should be either a number between 120 and 31536000 (one year) If this option is not specified, 3600 (one hour) is used. Special values are 0 for default value of 1 hour and 2147483647 (MAXINT32) for infinite lease time."
format="integer"
values="0 - 2147483647"
special-values="default (0), infinity (2147483647)" />
</setting> </setting>
<setting name="ipv6" > <setting name="ipv6" >
<property name="method" <property name="method"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff