diff options
Diffstat (limited to 'src/libnm-core-impl')
54 files changed, 6501 insertions, 1254 deletions
diff --git a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.c b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.c new file mode 100644 index 00000000..7e25e510 --- /dev/null +++ b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.c @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "libnm-glib-aux/nm-str-buf.h" +#include "libnm-core-intern/nm-meta-setting-base.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-base/nm-ethtool-base.h" + +#include "libnm-core-public/nm-setting-ethtool.h" + +#define INDENT 4 + +static const char * +_xml_escape_attr(NMStrBuf *sbuf, const char *value) +{ + gs_free char *s = NULL; + + nm_str_buf_reset(sbuf); + s = g_markup_escape_text(value, -1); + nm_str_buf_append_c(sbuf, '"'); + nm_str_buf_append(sbuf, s); + nm_str_buf_append_c(sbuf, '"'); + return nm_str_buf_get_str(sbuf); +} + +static const char * +_indent_level(guint num_spaces) +{ + static const char spaces[] = " "; + + nm_assert(num_spaces < G_N_ELEMENTS(spaces)); + return &spaces[G_N_ELEMENTS(spaces) - num_spaces - 1]; +} + +int +main(int argc, char *argv[]) +{ + nm_auto_str_buf NMStrBuf sbuf1 = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE); + const NMSettInfoSetting *sett_info_settings = nmtst_sett_info_settings(); + NMMetaSettingType meta_type; + + g_print("<!--\n" + " This file is generated.\n" + "\n" + " This XML contains meta data of NetworkManager connection profiles.\n" + "\n" + " NetworkManager's connection profiles are a bunch of settings, and this\n" + " contains the known properties. See also `man nm-settings-{dbus,nmcli,keyfile}`.\n" + "\n" + " Note that there are different manifestations of these properties. We have them\n" + " on the D-Bus API (`man nm-settings-dbus`), in keyfile format (`man " + "nm-settings-keyfile`)\n" + " in libnm's NMConnection and NMSetting API, and in nmcli (`man nm-settings-nmcli`).\n" + " There are similarities between these, but also subtle differencs. For example,\n" + " a property might not be shown in nmcli, or a property might be named different\n" + " on D-Bus or keyfile. Also, the data types may differ due to the differences of the\n" + " technology.\n" + "\n" + " This list of properties is not directly the properties as they are in any of\n" + " those manifestations. Instead, it's a general idea that this property exists in\n" + " NetworkManager. Whether and how it is represented in nmcli or keyfile, may differ.\n" + " The XML however aims to provide information for various backends.\n" + "\n" + " <setting> Attributes:\n" + " \"name\": the name of the setting.\n" + " \"gtype\": the typename of the NMSetting class in libnm.\n" + "\n" + " <property> Attributes:\n" + " \"name\": the name of the property.\n" + " \"is-deprecated\": whether this property is deprecated.\n" + " \"is-secret\": whether this property is a secret.\n" + " \"is-secret-flags\": whether this property is a secret flags property.\n" + " \"dbus-type\": if this property is exposed on D-Bus. In that case, this\n" + " is the D-Bus type format. Also, \"name\" is the actual name of the field\n" + " \"dbus-deprecated\": if this property is on D-Bus and that representation is\n" + " deprecated. This usually means, that there is a replacement D-Bus property\n" + " that should be used instead.\n" + " \"gprop-type\": if this is a GObject property in the NMSetting class, this\n" + " is the GParamSpec.value_type of the property.\n" + " \"is-setting-option\": whether the property is implemented in libnm's NMSetting\n" + " via the nm_setting_option_*() API.\n" + " -->\n"); + g_print("<nm-setting-docs>\n"); + for (meta_type = 0; meta_type < _NM_META_SETTING_TYPE_NUM; meta_type++) { + const NMSettInfoSetting *sis = &sett_info_settings[meta_type]; + const NMMetaSettingInfo *msi = &nm_meta_setting_infos[meta_type]; + nm_auto_unref_gtypeclass NMSettingClass *klass = NULL; + guint prop_idx; + GType gtype; + + gtype = msi->get_setting_gtype(); + klass = g_type_class_ref(gtype); + + g_print("%s<setting", _indent_level(INDENT)); + g_print(" name=%s", _xml_escape_attr(&sbuf1, msi->setting_name)); + g_print("\n%sgtype=%s", + _indent_level(INDENT + 9), + _xml_escape_attr(&sbuf1, g_type_name(gtype))); + g_print("\n%s>\n", _indent_level(INDENT + 9)); + + for (prop_idx = 0; prop_idx < sis->property_infos_len; prop_idx++) { + const NMSettInfoProperty *sip = &sis->property_infos[prop_idx]; + + if (nm_streq(sip->name, NM_SETTING_NAME)) + continue; + + g_print("%s<property", _indent_level(2 * INDENT)); + g_print(" name=%s", _xml_escape_attr(&sbuf1, sip->name)); + if (sip->is_deprecated) + g_print("\n%sis-deprecated=\"1\"", _indent_level(2 * INDENT + 10)); + if (sip->param_spec && NM_FLAGS_HAS(sip->param_spec->flags, NM_SETTING_PARAM_SECRET)) { + g_print("\n%sis-secret=\"1\"", _indent_level(2 * INDENT + 10)); + } + if (sip->param_spec + && G_PARAM_SPEC_VALUE_TYPE(sip->param_spec) == NM_TYPE_SETTING_SECRET_FLAGS) { + g_print("\n%sis-secret-flags=\"1\"", _indent_level(2 * INDENT + 10)); + } + if (sip->property_type->dbus_type) { + g_print("\n%sdbus-type=%s", + _indent_level(2 * INDENT + 10), + _xml_escape_attr(&sbuf1, (const char *) sip->property_type->dbus_type)); + } + if (sip->dbus_deprecated) { + nm_assert(sip->property_type->dbus_type); + g_print("\n%sdbus-deprecated=\"1\"", _indent_level(2 * INDENT + 10)); + } + if (sip->param_spec) { + nm_assert(nm_streq(sip->name, sip->param_spec->name)); + g_print("\n%sgprop-type=%s", + _indent_level(2 * INDENT + 10), + _xml_escape_attr(&sbuf1, + g_type_name(G_PARAM_SPEC_VALUE_TYPE(sip->param_spec)))); + } + g_print("\n%s/>\n", _indent_level(2 * INDENT + 10)); + } + + if (nm_streq(msi->setting_name, NM_SETTING_ETHTOOL_SETTING_NAME)) { + NMEthtoolID ethtool_id; + + /* NMSettingEthtool's properties are "gendata" options. They are implemented differently. */ + for (ethtool_id = _NM_ETHTOOL_ID_FIRST; ethtool_id <= _NM_ETHTOOL_ID_LAST; + ethtool_id++) { + g_print("%s<property", _indent_level(2 * INDENT)); + g_print(" name=%s", _xml_escape_attr(&sbuf1, nm_ethtool_data[ethtool_id]->optname)); + g_print( + "\n%sdbus-type=%s", + _indent_level(2 * INDENT + 10), + _xml_escape_attr(&sbuf1, + (const char *) nm_ethtool_id_get_variant_type(ethtool_id))); + g_print("\n%sis-setting-option=\"1\"", _indent_level(2 * INDENT + 10)); + g_print("\n%s/>\n", _indent_level(2 * INDENT + 10)); + } + } + + g_print("%s</setting>\n", _indent_level(INDENT)); + } + g_print("</nm-setting-docs>\n"); + return 0; +} diff --git a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in new file mode 100644 index 00000000..3b210b16 --- /dev/null +++ b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in @@ -0,0 +1,2492 @@ +<!-- + This file is generated. + + This XML contains meta data of NetworkManager connection profiles. + + NetworkManager's connection profiles are a bunch of settings, and this + contains the known properties. See also `man nm-settings-{dbus,nmcli,keyfile}`. + + Note that there are different manifestations of these properties. We have them + on the D-Bus API (`man nm-settings-dbus`), in keyfile format (`man nm-settings-keyfile`) + in libnm's NMConnection and NMSetting API, and in nmcli (`man nm-settings-nmcli`). + There are similarities between these, but also subtle differencs. For example, + a property might not be shown in nmcli, or a property might be named different + on D-Bus or keyfile. Also, the data types may differ due to the differences of the + technology. + + This list of properties is not directly the properties as they are in any of + those manifestations. Instead, it's a general idea that this property exists in + NetworkManager. Whether and how it is represented in nmcli or keyfile, may differ. + The XML however aims to provide information for various backends. + + <setting> Attributes: + "name": the name of the setting. + "gtype": the typename of the NMSetting class in libnm. + + <property> Attributes: + "name": the name of the property. + "is-deprecated": whether this property is deprecated. + "is-secret": whether this property is a secret. + "is-secret-flags": whether this property is a secret flags property. + "dbus-type": if this property is exposed on D-Bus. In that case, this + is the D-Bus type format. Also, "name" is the actual name of the field + "dbus-deprecated": if this property is on D-Bus and that representation is + deprecated. This usually means, that there is a replacement D-Bus property + that should be used instead. + "gprop-type": if this is a GObject property in the NMSetting class, this + is the GParamSpec.value_type of the property. + "is-setting-option": whether the property is implemented in libnm's NMSetting + via the nm_setting_option_*() API. + --> +<nm-setting-docs> + <setting name="6lowpan" + gtype="NMSetting6Lowpan" + > + <property name="parent" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="802-11-olpc-mesh" + gtype="NMSettingOlpcMesh" + > + <property name="channel" + dbus-type="u" + gprop-type="guint" + /> + <property name="dhcp-anycast-address" + dbus-type="ay" + gprop-type="gchararray" + /> + <property name="ssid" + dbus-type="ay" + gprop-type="GBytes" + /> + </setting> + <setting name="802-11-wireless" + gtype="NMSettingWireless" + > + <property name="ap-isolation" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="assigned-mac-address" + dbus-type="s" + /> + <property name="band" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="bssid" + dbus-type="ay" + gprop-type="gchararray" + /> + <property name="channel" + dbus-type="u" + gprop-type="guint" + /> + <property name="cloned-mac-address" + dbus-type="ay" + dbus-deprecated="1" + gprop-type="gchararray" + /> + <property name="generate-mac-address-mask" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="hidden" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="mac-address" + dbus-type="ay" + gprop-type="gchararray" + /> + <property name="mac-address-blacklist" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="mac-address-randomization" + is-deprecated="1" + dbus-type="u" + gprop-type="guint" + /> + <property name="mode" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + <property name="powersave" + dbus-type="u" + gprop-type="guint" + /> + <property name="rate" + dbus-type="u" + gprop-type="guint" + /> + <property name="security" + dbus-type="s" + dbus-deprecated="1" + /> + <property name="seen-bssids" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="ssid" + dbus-type="ay" + gprop-type="GBytes" + /> + <property name="tx-power" + dbus-type="u" + gprop-type="guint" + /> + <property name="wake-on-wlan" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="802-11-wireless-security" + gtype="NMSettingWirelessSecurity" + > + <property name="auth-alg" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="fils" + dbus-type="i" + gprop-type="gint" + /> + <property name="group" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="key-mgmt" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="leap-password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="leap-password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="leap-username" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="pairwise" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="pmf" + dbus-type="i" + gprop-type="gint" + /> + <property name="proto" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="psk" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="psk-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="wep-key-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="wep-key-type" + dbus-type="u" + gprop-type="NMWepKeyType" + /> + <property name="wep-key0" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="wep-key1" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="wep-key2" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="wep-key3" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="wep-tx-keyidx" + dbus-type="u" + gprop-type="guint" + /> + <property name="wps-method" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="802-1x" + gtype="NMSetting8021x" + > + <property name="altsubject-matches" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="anonymous-identity" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="auth-timeout" + dbus-type="i" + gprop-type="gint" + /> + <property name="ca-cert" + dbus-type="ay" + gprop-type="GBytes" + /> + <property name="ca-cert-password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="ca-cert-password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="ca-path" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="client-cert" + dbus-type="ay" + gprop-type="GBytes" + /> + <property name="client-cert-password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="client-cert-password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="domain-match" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="domain-suffix-match" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="eap" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="identity" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="optional" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="pac-file" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="password-raw" + is-secret="1" + dbus-type="ay" + gprop-type="GBytes" + /> + <property name="password-raw-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="phase1-auth-flags" + dbus-type="u" + gprop-type="guint" + /> + <property name="phase1-fast-provisioning" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase1-peaplabel" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase1-peapver" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase2-altsubject-matches" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="phase2-auth" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase2-autheap" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase2-ca-cert" + dbus-type="ay" + gprop-type="GBytes" + /> + <property name="phase2-ca-cert-password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase2-ca-cert-password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="phase2-ca-path" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase2-client-cert" + dbus-type="ay" + gprop-type="GBytes" + /> + <property name="phase2-client-cert-password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase2-client-cert-password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="phase2-domain-match" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase2-domain-suffix-match" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase2-private-key" + dbus-type="ay" + gprop-type="GBytes" + /> + <property name="phase2-private-key-password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="phase2-private-key-password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="phase2-subject-match" + is-deprecated="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="pin" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="pin-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="private-key" + dbus-type="ay" + gprop-type="GBytes" + /> + <property name="private-key-password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="private-key-password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="subject-match" + is-deprecated="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="system-ca-certs" + dbus-type="b" + gprop-type="gboolean" + /> + </setting> + <setting name="802-3-ethernet" + gtype="NMSettingWired" + > + <property name="accept-all-mac-addresses" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="assigned-mac-address" + dbus-type="s" + /> + <property name="auto-negotiate" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="cloned-mac-address" + dbus-type="ay" + dbus-deprecated="1" + gprop-type="gchararray" + /> + <property name="duplex" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="generate-mac-address-mask" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="mac-address" + dbus-type="ay" + gprop-type="gchararray" + /> + <property name="mac-address-blacklist" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + <property name="port" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="s390-nettype" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="s390-options" + dbus-type="a{ss}" + gprop-type="GHashTable" + /> + <property name="s390-subchannels" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="speed" + dbus-type="u" + gprop-type="guint" + /> + <property name="wake-on-lan" + dbus-type="u" + gprop-type="guint" + /> + <property name="wake-on-lan-password" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="adsl" + gtype="NMSettingAdsl" + > + <property name="encapsulation" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="protocol" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="username" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="vci" + dbus-type="u" + gprop-type="guint" + /> + <property name="vpi" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="bluetooth" + gtype="NMSettingBluetooth" + > + <property name="bdaddr" + dbus-type="ay" + gprop-type="gchararray" + /> + <property name="type" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="bond" + gtype="NMSettingBond" + > + <property name="interface-name" + dbus-type="s" + dbus-deprecated="1" + /> + <property name="options" + dbus-type="a{ss}" + gprop-type="GHashTable" + /> + </setting> + <setting name="bond-port" + gtype="NMSettingBondPort" + > + <property name="queue-id" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="bridge" + gtype="NMSettingBridge" + > + <property name="ageing-time" + dbus-type="u" + gprop-type="guint" + /> + <property name="forward-delay" + dbus-type="u" + gprop-type="guint" + /> + <property name="group-address" + dbus-type="ay" + gprop-type="gchararray" + /> + <property name="group-forward-mask" + dbus-type="u" + gprop-type="guint" + /> + <property name="hello-time" + dbus-type="u" + gprop-type="guint" + /> + <property name="interface-name" + dbus-type="s" + dbus-deprecated="1" + /> + <property name="mac-address" + is-deprecated="1" + dbus-type="ay" + gprop-type="gchararray" + /> + <property name="max-age" + dbus-type="u" + gprop-type="guint" + /> + <property name="multicast-hash-max" + dbus-type="u" + gprop-type="guint" + /> + <property name="multicast-last-member-count" + dbus-type="u" + gprop-type="guint" + /> + <property name="multicast-last-member-interval" + dbus-type="t" + gprop-type="guint64" + /> + <property name="multicast-membership-interval" + dbus-type="t" + gprop-type="guint64" + /> + <property name="multicast-querier" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="multicast-querier-interval" + dbus-type="t" + gprop-type="guint64" + /> + <property name="multicast-query-interval" + dbus-type="t" + gprop-type="guint64" + /> + <property name="multicast-query-response-interval" + dbus-type="t" + gprop-type="guint64" + /> + <property name="multicast-query-use-ifaddr" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="multicast-router" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="multicast-snooping" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="multicast-startup-query-count" + dbus-type="u" + gprop-type="guint" + /> + <property name="multicast-startup-query-interval" + dbus-type="t" + gprop-type="guint64" + /> + <property name="priority" + dbus-type="u" + gprop-type="guint" + /> + <property name="stp" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="vlan-default-pvid" + dbus-type="u" + gprop-type="guint" + /> + <property name="vlan-filtering" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="vlan-protocol" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="vlan-stats-enabled" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="vlans" + dbus-type="aa{sv}" + gprop-type="GPtrArray" + /> + </setting> + <setting name="bridge-port" + gtype="NMSettingBridgePort" + > + <property name="hairpin-mode" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="path-cost" + dbus-type="u" + gprop-type="guint" + /> + <property name="priority" + dbus-type="u" + gprop-type="guint" + /> + <property name="vlans" + dbus-type="aa{sv}" + gprop-type="GPtrArray" + /> + </setting> + <setting name="cdma" + gtype="NMSettingCdma" + > + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + <property name="number" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="username" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="connection" + gtype="NMSettingConnection" + > + <property name="auth-retries" + dbus-type="i" + gprop-type="gint" + /> + <property name="autoconnect" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="autoconnect-priority" + dbus-type="i" + gprop-type="gint" + /> + <property name="autoconnect-retries" + dbus-type="i" + gprop-type="gint" + /> + <property name="autoconnect-slaves" + dbus-type="i" + gprop-type="NMSettingConnectionAutoconnectSlaves" + /> + <property name="dns-over-tls" + dbus-type="i" + gprop-type="gint" + /> + <property name="gateway-ping-timeout" + dbus-type="u" + gprop-type="guint" + /> + <property name="id" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="interface-name" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="lldp" + dbus-type="i" + gprop-type="gint" + /> + <property name="llmnr" + dbus-type="i" + gprop-type="gint" + /> + <property name="master" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="mdns" + dbus-type="i" + gprop-type="gint" + /> + <property name="metered" + dbus-type="i" + gprop-type="NMMetered" + /> + <property name="mptcp-flags" + dbus-type="u" + gprop-type="guint" + /> + <property name="mud-url" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="multi-connect" + dbus-type="i" + gprop-type="gint" + /> + <property name="permissions" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="read-only" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="secondaries" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="slave-type" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="stable-id" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="timestamp" + dbus-type="t" + gprop-type="guint64" + /> + <property name="type" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="uuid" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="wait-activation-delay" + dbus-type="i" + gprop-type="gint" + /> + <property name="wait-device-timeout" + dbus-type="i" + gprop-type="gint" + /> + <property name="zone" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="dcb" + gtype="NMSettingDcb" + > + <property name="app-fcoe-flags" + dbus-type="u" + gprop-type="NMSettingDcbFlags" + /> + <property name="app-fcoe-mode" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="app-fcoe-priority" + dbus-type="i" + gprop-type="gint" + /> + <property name="app-fip-flags" + dbus-type="u" + gprop-type="NMSettingDcbFlags" + /> + <property name="app-fip-priority" + dbus-type="i" + gprop-type="gint" + /> + <property name="app-iscsi-flags" + dbus-type="u" + gprop-type="NMSettingDcbFlags" + /> + <property name="app-iscsi-priority" + dbus-type="i" + gprop-type="gint" + /> + <property name="priority-bandwidth" + dbus-type="au" + gprop-type="GArray" + /> + <property name="priority-flow-control" + dbus-type="au" + gprop-type="GArray" + /> + <property name="priority-flow-control-flags" + dbus-type="u" + gprop-type="NMSettingDcbFlags" + /> + <property name="priority-group-bandwidth" + dbus-type="au" + gprop-type="GArray" + /> + <property name="priority-group-flags" + dbus-type="u" + gprop-type="NMSettingDcbFlags" + /> + <property name="priority-group-id" + dbus-type="au" + gprop-type="GArray" + /> + <property name="priority-strict-bandwidth" + dbus-type="au" + gprop-type="GArray" + /> + <property name="priority-traffic-class" + dbus-type="au" + gprop-type="GArray" + /> + </setting> + <setting name="dummy" + gtype="NMSettingDummy" + > + </setting> + <setting name="ethtool" + gtype="NMSettingEthtool" + > + <property name="coalesce-adaptive-rx" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-adaptive-tx" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-pkt-rate-high" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-pkt-rate-low" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-rx-frames" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-rx-frames-high" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-rx-frames-irq" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-rx-frames-low" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-rx-usecs" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-rx-usecs-high" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-rx-usecs-irq" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-rx-usecs-low" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-sample-interval" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-stats-block-usecs" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-tx-frames" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-tx-frames-high" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-tx-frames-irq" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-tx-frames-low" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-tx-usecs" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-tx-usecs-high" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-tx-usecs-irq" + dbus-type="u" + is-setting-option="1" + /> + <property name="coalesce-tx-usecs-low" + dbus-type="u" + is-setting-option="1" + /> + <property name="feature-esp-hw-offload" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-esp-tx-csum-hw-offload" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-fcoe-mtu" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-gro" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-gso" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-highdma" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-hw-tc-offload" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-l2-fwd-offload" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-loopback" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-lro" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-macsec-hw-offload" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-ntuple" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rxhash" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rxvlan" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx-all" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx-fcs" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx-gro-hw" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx-gro-list" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx-udp-gro-forwarding" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx-udp_tunnel-port-offload" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx-vlan-filter" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx-vlan-stag-filter" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-rx-vlan-stag-hw-parse" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-sg" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tls-hw-record" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tls-hw-rx-offload" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tls-hw-tx-offload" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tso" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-txvlan" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-checksum-fcoe-crc" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-checksum-ipv4" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-checksum-ipv6" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-checksum-ip-generic" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-checksum-sctp" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-esp-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-fcoe-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-gre-csum-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-gre-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-gso-list" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-gso-partial" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-gso-robust" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-ipxip4-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-ipxip6-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-nocache-copy" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-scatter-gather" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-scatter-gather-fraglist" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-sctp-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-tcp6-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-tcp-ecn-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-tcp-mangleid-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-tcp-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-tunnel-remcsum-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-udp-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-udp_tnl-csum-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-udp_tnl-segmentation" + dbus-type="b" + is-setting-option="1" + /> + <property name="feature-tx-vlan-stag-hw-insert" + dbus-type="b" + is-setting-option="1" + /> + <property name="pause-autoneg" + dbus-type="b" + is-setting-option="1" + /> + <property name="pause-rx" + dbus-type="b" + is-setting-option="1" + /> + <property name="pause-tx" + dbus-type="b" + is-setting-option="1" + /> + <property name="ring-rx" + dbus-type="u" + is-setting-option="1" + /> + <property name="ring-rx-jumbo" + dbus-type="u" + is-setting-option="1" + /> + <property name="ring-rx-mini" + dbus-type="u" + is-setting-option="1" + /> + <property name="ring-tx" + dbus-type="u" + is-setting-option="1" + /> + </setting> + <setting name="generic" + gtype="NMSettingGeneric" + > + </setting> + <setting name="gsm" + gtype="NMSettingGsm" + > + <property name="allowed-bands" + dbus-type="u" + dbus-deprecated="1" + /> + <property name="apn" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="auto-config" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="device-id" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="home-only" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + <property name="network-id" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="network-type" + dbus-type="i" + dbus-deprecated="1" + /> + <property name="number" + is-deprecated="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="pin" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="pin-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="sim-id" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="sim-operator-id" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="username" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="hostname" + gtype="NMSettingHostname" + > + <property name="from-dhcp" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="from-dns-lookup" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="only-from-default" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="priority" + dbus-type="i" + gprop-type="gint" + /> + </setting> + <setting name="infiniband" + gtype="NMSettingInfiniband" + > + <property name="mac-address" + dbus-type="ay" + gprop-type="gchararray" + /> + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + <property name="p-key" + dbus-type="i" + gprop-type="gint" + /> + <property name="parent" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="transport-mode" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="ip-tunnel" + gtype="NMSettingIPTunnel" + > + <property name="encapsulation-limit" + dbus-type="u" + gprop-type="guint" + /> + <property name="flags" + dbus-type="u" + gprop-type="guint" + /> + <property name="flow-label" + dbus-type="u" + gprop-type="guint" + /> + <property name="fwmark" + dbus-type="u" + gprop-type="guint" + /> + <property name="input-key" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="local" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="mode" + dbus-type="u" + gprop-type="guint" + /> + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + <property name="output-key" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="parent" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="path-mtu-discovery" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="remote" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="tos" + dbus-type="u" + gprop-type="guint" + /> + <property name="ttl" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="ipv4" + gtype="NMSettingIP4Config" + > + <property name="address-data" + dbus-type="aa{sv}" + /> + <property name="address-labels" + dbus-type="as" + dbus-deprecated="1" + /> + <property name="addresses" + dbus-type="aau" + dbus-deprecated="1" + gprop-type="GPtrArray" + /> + <property name="auto-route-ext-gw" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="dad-timeout" + dbus-type="i" + gprop-type="gint" + /> + <property name="dhcp-client-id" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="dhcp-fqdn" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="dhcp-hostname" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="dhcp-hostname-flags" + dbus-type="u" + gprop-type="guint" + /> + <property name="dhcp-iaid" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="dhcp-reject-servers" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="dhcp-send-hostname" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="dhcp-timeout" + dbus-type="i" + gprop-type="gint" + /> + <property name="dhcp-vendor-class-identifier" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="dns" + dbus-type="au" + dbus-deprecated="1" + gprop-type="GStrv" + /> + <property name="dns-data" + dbus-type="as" + /> + <property name="dns-options" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="dns-priority" + dbus-type="i" + gprop-type="gint" + /> + <property name="dns-search" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="gateway" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="ignore-auto-dns" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="ignore-auto-routes" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="link-local" + dbus-type="i" + gprop-type="gint" + /> + <property name="may-fail" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="method" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="never-default" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="required-timeout" + dbus-type="i" + gprop-type="gint" + /> + <property name="route-data" + dbus-type="aa{sv}" + /> + <property name="route-metric" + dbus-type="x" + gprop-type="gint64" + /> + <property name="route-table" + dbus-type="u" + gprop-type="guint" + /> + <property name="routes" + dbus-type="aau" + dbus-deprecated="1" + gprop-type="GPtrArray" + /> + <property name="routing-rules" + dbus-type="aa{sv}" + /> + </setting> + <setting name="ipv6" + gtype="NMSettingIP6Config" + > + <property name="addr-gen-mode" + dbus-type="i" + gprop-type="gint" + /> + <property name="address-data" + dbus-type="aa{sv}" + /> + <property name="addresses" + dbus-type="a(ayuay)" + dbus-deprecated="1" + gprop-type="GPtrArray" + /> + <property name="auto-route-ext-gw" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="dad-timeout" + dbus-type="i" + gprop-type="gint" + /> + <property name="dhcp-duid" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="dhcp-hostname" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="dhcp-hostname-flags" + dbus-type="u" + gprop-type="guint" + /> + <property name="dhcp-iaid" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="dhcp-reject-servers" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="dhcp-send-hostname" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="dhcp-timeout" + dbus-type="i" + gprop-type="gint" + /> + <property name="dns" + dbus-type="aay" + dbus-deprecated="1" + gprop-type="GStrv" + /> + <property name="dns-data" + dbus-type="as" + /> + <property name="dns-options" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="dns-priority" + dbus-type="i" + gprop-type="gint" + /> + <property name="dns-search" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="gateway" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="ignore-auto-dns" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="ignore-auto-routes" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="ip6-privacy" + dbus-type="i" + gprop-type="NMSettingIP6ConfigPrivacy" + /> + <property name="may-fail" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="method" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + <property name="never-default" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="ra-timeout" + dbus-type="i" + gprop-type="gint" + /> + <property name="required-timeout" + dbus-type="i" + gprop-type="gint" + /> + <property name="route-data" + dbus-type="aa{sv}" + /> + <property name="route-metric" + dbus-type="x" + gprop-type="gint64" + /> + <property name="route-table" + dbus-type="u" + gprop-type="guint" + /> + <property name="routes" + dbus-type="a(ayuayu)" + dbus-deprecated="1" + gprop-type="GPtrArray" + /> + <property name="routing-rules" + dbus-type="aa{sv}" + /> + <property name="token" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="loopback" + gtype="NMSettingLoopback" + > + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="macsec" + gtype="NMSettingMacsec" + > + <property name="encrypt" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="mka-cak" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="mka-cak-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="mka-ckn" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="mode" + dbus-type="i" + gprop-type="gint" + /> + <property name="parent" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="port" + dbus-type="i" + gprop-type="gint" + /> + <property name="send-sci" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="validation" + dbus-type="i" + gprop-type="gint" + /> + </setting> + <setting name="macvlan" + gtype="NMSettingMacvlan" + > + <property name="mode" + dbus-type="u" + gprop-type="guint" + /> + <property name="parent" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="promiscuous" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="tap" + dbus-type="b" + gprop-type="gboolean" + /> + </setting> + <setting name="match" + gtype="NMSettingMatch" + > + <property name="driver" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="interface-name" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="kernel-command-line" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="path" + dbus-type="as" + gprop-type="GStrv" + /> + </setting> + <setting name="ovs-bridge" + gtype="NMSettingOvsBridge" + > + <property name="datapath-type" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="fail-mode" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="mcast-snooping-enable" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="rstp-enable" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="stp-enable" + dbus-type="b" + gprop-type="gboolean" + /> + </setting> + <setting name="ovs-dpdk" + gtype="NMSettingOvsDpdk" + > + <property name="devargs" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="n-rxq" + dbus-type="u" + gprop-type="guint" + /> + <property name="n-rxq-desc" + dbus-type="u" + gprop-type="guint" + /> + <property name="n-txq-desc" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="ovs-external-ids" + gtype="NMSettingOvsExternalIDs" + > + <property name="data" + dbus-type="a{ss}" + gprop-type="GHashTable" + /> + </setting> + <setting name="ovs-interface" + gtype="NMSettingOvsInterface" + > + <property name="ofport-request" + dbus-type="u" + gprop-type="guint" + /> + <property name="type" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="ovs-other-config" + gtype="NMSettingOvsOtherConfig" + > + <property name="data" + dbus-type="a{ss}" + gprop-type="GHashTable" + /> + </setting> + <setting name="ovs-patch" + gtype="NMSettingOvsPatch" + > + <property name="peer" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="ovs-port" + gtype="NMSettingOvsPort" + > + <property name="bond-downdelay" + dbus-type="u" + gprop-type="guint" + /> + <property name="bond-mode" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="bond-updelay" + dbus-type="u" + gprop-type="guint" + /> + <property name="lacp" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="tag" + dbus-type="u" + gprop-type="guint" + /> + <property name="trunks" + dbus-type="aa{sv}" + gprop-type="GPtrArray" + /> + <property name="vlan-mode" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="ppp" + gtype="NMSettingPpp" + > + <property name="baud" + dbus-type="u" + gprop-type="guint" + /> + <property name="crtscts" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="lcp-echo-failure" + dbus-type="u" + gprop-type="guint" + /> + <property name="lcp-echo-interval" + dbus-type="u" + gprop-type="guint" + /> + <property name="mppe-stateful" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="mru" + dbus-type="u" + gprop-type="guint" + /> + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + <property name="no-vj-comp" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="noauth" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="nobsdcomp" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="nodeflate" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="refuse-chap" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="refuse-eap" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="refuse-mschap" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="refuse-mschapv2" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="refuse-pap" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="require-mppe" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="require-mppe-128" + dbus-type="b" + gprop-type="gboolean" + /> + </setting> + <setting name="pppoe" + gtype="NMSettingPppoe" + > + <property name="parent" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="password-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + <property name="service" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="username" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="proxy" + gtype="NMSettingProxy" + > + <property name="browser-only" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="method" + dbus-type="i" + gprop-type="gint" + /> + <property name="pac-script" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="pac-url" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="serial" + gtype="NMSettingSerial" + > + <property name="baud" + dbus-type="u" + gprop-type="guint" + /> + <property name="bits" + dbus-type="u" + gprop-type="guint" + /> + <property name="parity" + dbus-type="y" + gprop-type="NMSettingSerialParity" + /> + <property name="send-delay" + dbus-type="t" + gprop-type="guint64" + /> + <property name="stopbits" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="sriov" + gtype="NMSettingSriov" + > + <property name="autoprobe-drivers" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="total-vfs" + dbus-type="u" + gprop-type="guint" + /> + <property name="vfs" + dbus-type="aa{sv}" + gprop-type="GPtrArray" + /> + </setting> + <setting name="tc" + gtype="NMSettingTCConfig" + > + <property name="qdiscs" + dbus-type="aa{sv}" + gprop-type="GPtrArray" + /> + <property name="tfilters" + dbus-type="aa{sv}" + gprop-type="GPtrArray" + /> + </setting> + <setting name="team" + gtype="NMSettingTeam" + > + <property name="config" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="interface-name" + dbus-type="s" + dbus-deprecated="1" + /> + <property name="link-watchers" + dbus-type="aa{sv}" + gprop-type="GPtrArray" + /> + <property name="mcast-rejoin-count" + dbus-type="i" + gprop-type="gint" + /> + <property name="mcast-rejoin-interval" + dbus-type="i" + gprop-type="gint" + /> + <property name="notify-peers-count" + dbus-type="i" + gprop-type="gint" + /> + <property name="notify-peers-interval" + dbus-type="i" + gprop-type="gint" + /> + <property name="runner" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="runner-active" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="runner-agg-select-policy" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="runner-fast-rate" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="runner-hwaddr-policy" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="runner-min-ports" + dbus-type="i" + gprop-type="gint" + /> + <property name="runner-sys-prio" + dbus-type="i" + gprop-type="gint" + /> + <property name="runner-tx-balancer" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="runner-tx-balancer-interval" + dbus-type="i" + gprop-type="gint" + /> + <property name="runner-tx-hash" + dbus-type="as" + gprop-type="GStrv" + /> + </setting> + <setting name="team-port" + gtype="NMSettingTeamPort" + > + <property name="config" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="lacp-key" + dbus-type="i" + gprop-type="gint" + /> + <property name="lacp-prio" + dbus-type="i" + gprop-type="gint" + /> + <property name="link-watchers" + dbus-type="aa{sv}" + gprop-type="GPtrArray" + /> + <property name="prio" + dbus-type="i" + gprop-type="gint" + /> + <property name="queue-id" + dbus-type="i" + gprop-type="gint" + /> + <property name="sticky" + dbus-type="b" + gprop-type="gboolean" + /> + </setting> + <setting name="tun" + gtype="NMSettingTun" + > + <property name="group" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="mode" + dbus-type="u" + gprop-type="guint" + /> + <property name="multi-queue" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="owner" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="pi" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="vnet-hdr" + dbus-type="b" + gprop-type="gboolean" + /> + </setting> + <setting name="user" + gtype="NMSettingUser" + > + <property name="data" + dbus-type="a{ss}" + gprop-type="GHashTable" + /> + </setting> + <setting name="veth" + gtype="NMSettingVeth" + > + <property name="peer" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="vlan" + gtype="NMSettingVlan" + > + <property name="egress-priority-map" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="flags" + dbus-type="u" + gprop-type="NMVlanFlags" + /> + <property name="id" + dbus-type="u" + gprop-type="guint" + /> + <property name="ingress-priority-map" + dbus-type="as" + gprop-type="GStrv" + /> + <property name="interface-name" + dbus-type="s" + dbus-deprecated="1" + /> + <property name="parent" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="protocol" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="vpn" + gtype="NMSettingVpn" + > + <property name="data" + dbus-type="a{ss}" + gprop-type="GHashTable" + /> + <property name="persistent" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="secrets" + is-secret="1" + dbus-type="a{ss}" + gprop-type="GHashTable" + /> + <property name="service-type" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="timeout" + dbus-type="u" + gprop-type="guint" + /> + <property name="user-name" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="vrf" + gtype="NMSettingVrf" + > + <property name="table" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="vxlan" + gtype="NMSettingVxlan" + > + <property name="ageing" + dbus-type="u" + gprop-type="guint" + /> + <property name="destination-port" + dbus-type="u" + gprop-type="guint" + /> + <property name="id" + dbus-type="u" + gprop-type="guint" + /> + <property name="l2-miss" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="l3-miss" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="learning" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="limit" + dbus-type="u" + gprop-type="guint" + /> + <property name="local" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="parent" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="proxy" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="remote" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="rsc" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="source-port-max" + dbus-type="u" + gprop-type="guint" + /> + <property name="source-port-min" + dbus-type="u" + gprop-type="guint" + /> + <property name="tos" + dbus-type="u" + gprop-type="guint" + /> + <property name="ttl" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="wifi-p2p" + gtype="NMSettingWifiP2P" + > + <property name="peer" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="wfd-ies" + dbus-type="ay" + gprop-type="GBytes" + /> + <property name="wps-method" + dbus-type="u" + gprop-type="guint" + /> + </setting> + <setting name="wimax" + gtype="NMSettingWimax" + > + <property name="mac-address" + is-deprecated="1" + dbus-type="ay" + gprop-type="gchararray" + /> + <property name="network-name" + is-deprecated="1" + dbus-type="s" + gprop-type="gchararray" + /> + </setting> + <setting name="wireguard" + gtype="NMSettingWireGuard" + > + <property name="fwmark" + dbus-type="u" + gprop-type="guint" + /> + <property name="ip4-auto-default-route" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="ip6-auto-default-route" + dbus-type="i" + gprop-type="NMTernary" + /> + <property name="listen-port" + dbus-type="u" + gprop-type="guint" + /> + <property name="mtu" + dbus-type="u" + gprop-type="guint" + /> + <property name="peer-routes" + dbus-type="b" + gprop-type="gboolean" + /> + <property name="peers" + dbus-type="aa{sv}" + /> + <property name="private-key" + is-secret="1" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="private-key-flags" + is-secret-flags="1" + dbus-type="u" + gprop-type="NMSettingSecretFlags" + /> + </setting> + <setting name="wpan" + gtype="NMSettingWpan" + > + <property name="channel" + dbus-type="i" + gprop-type="gint" + /> + <property name="mac-address" + dbus-type="s" + gprop-type="gchararray" + /> + <property name="page" + dbus-type="i" + gprop-type="gint" + /> + <property name="pan-id" + dbus-type="u" + gprop-type="guint" + /> + <property name="short-address" + dbus-type="u" + gprop-type="guint" + /> + </setting> +</nm-setting-docs> diff --git a/src/libnm-core-impl/meson.build b/src/libnm-core-impl/meson.build index 83c29085..6408ae17 100644 --- a/src/libnm-core-impl/meson.build +++ b/src/libnm-core-impl/meson.build @@ -24,6 +24,7 @@ libnm_core_settings_sources = files( 'nm-setting-ip-tunnel.c', 'nm-setting-ip4-config.c', 'nm-setting-ip6-config.c', + 'nm-setting-loopback.c', 'nm-setting-macsec.c', 'nm-setting-macvlan.c', 'nm-setting-match.c', @@ -32,6 +33,7 @@ libnm_core_settings_sources = files( 'nm-setting-ovs-dpdk.c', 'nm-setting-ovs-external-ids.c', 'nm-setting-ovs-interface.c', + 'nm-setting-ovs-other-config.c', 'nm-setting-ovs-patch.c', 'nm-setting-ovs-port.c', 'nm-setting-ppp.c', @@ -60,7 +62,6 @@ libnm_core_settings_sources = files( libnm_core_impl_sources = files( 'nm-connection.c', - 'nm-dbus-utils.c', 'nm-errors.c', 'nm-keyfile-utils.c', 'nm-keyfile.c', @@ -88,3 +89,52 @@ libnm_core_impl = static_library( uuid_dep, ], ) + +############################################################################### + +gen_metadata_nm_settings_libnm_core = executable( + 'gen-metadata-nm-settings-libnm-core', + files( + 'gen-metadata-nm-settings-libnm-core.c', + ), + dependencies: [ + libnm_core_public_dep, + ], + link_with: [ + libnm_core_aux_intern, + libnm_core_impl, + libnm_crypto, + libnm_base, + libnm_systemd_shared, + libnm_log_null, + libnm_glib_aux, + libnm_std_aux, + libc_siphash, + ], + link_args: ldflags_linker_script_binary, + link_depends: linker_script_binary, +) + +if enable_docs + gen_metadata_nm_settings_libnm_core_xml = custom_target( + 'gen-metadata-nm-settings-libnm-core.xml', + output: 'gen-metadata-nm-settings-libnm-core.xml', + command: [ gen_metadata_nm_settings_libnm_core ], + capture: true, + ) + + test( + 'check-local-gen-metadata-nm-settings-libnm-core', + find_program(join_paths(source_root, 'tools', 'check-compare-generated.sh')), + args: [ + source_root + '/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in', + gen_metadata_nm_settings_libnm_core_xml, + ], + ) +else + gen_metadata_nm_settings_libnm_core_xml = configure_file( + input: 'gen-metadata-nm-settings-libnm-core.xml.in', + output: '@BASENAME@', + configuration: configuration_data(), + ) +endif diff --git a/src/libnm-core-impl/nm-connection.c b/src/libnm-core-impl/nm-connection.c index 2f5bf357..3a9eda0e 100644 --- a/src/libnm-core-impl/nm-connection.c +++ b/src/libnm-core-impl/nm-connection.c @@ -11,6 +11,7 @@ #include <arpa/inet.h> #include "libnm-glib-aux/nm-uuid.h" +#include "libnm-glib-aux/nm-ref-string.h" #include "nm-connection-private.h" #include "nm-utils.h" #include "nm-setting-private.h" @@ -54,39 +55,12 @@ static gboolean _nm_connection_clear_settings(NMConnection *connection, NMConnec /*****************************************************************************/ -#undef NM_IS_SIMPLE_CONNECTION -#define NM_IS_SIMPLE_CONNECTION(self) \ - ({ \ - gconstpointer _self1 = (self); \ - gboolean _result; \ - \ - _result = \ - (_self1 \ - && (((GTypeInstance *) _self1)->g_class == _nm_simple_connection_class_instance)); \ - \ - nm_assert(_result == G_TYPE_CHECK_INSTANCE_TYPE(_self1, NM_TYPE_SIMPLE_CONNECTION)); \ - \ - _result; \ - }) - -#undef NM_IS_CONNECTION -#define NM_IS_CONNECTION(self) \ - ({ \ - gconstpointer _self0 = (self); \ - \ - (_self0 \ - && (NM_IS_SIMPLE_CONNECTION(_self0) \ - || G_TYPE_CHECK_INSTANCE_TYPE(_self0, NM_TYPE_CONNECTION))); \ - }) - -/*****************************************************************************/ - void _nm_connection_private_clear(NMConnectionPrivate *priv) { if (priv->self) { _nm_connection_clear_settings(priv->self, priv); - nm_clear_g_free(&priv->path); + nm_clear_pointer(&priv->path, nm_ref_string_unref); priv->self = NULL; } } @@ -124,19 +98,19 @@ _nm_connection_get_private_from_qdata(NMConnection *connection) return priv; } -#define NM_CONNECTION_GET_PRIVATE(connection) \ - ({ \ - NMConnection *_connection = (connection); \ - NMConnectionPrivate *_priv; \ - \ - if (G_LIKELY(NM_IS_SIMPLE_CONNECTION(_connection))) \ - _priv = (gpointer) (&(((char *) _connection)[_nm_simple_connection_private_offset])); \ - else \ - _priv = _nm_connection_get_private_from_qdata(_connection); \ - \ - nm_assert(_priv && _priv->self == _connection); \ - \ - _priv; \ +#define NM_CONNECTION_GET_PRIVATE(connection) \ + ({ \ + NMConnection *_connection = (connection); \ + NMConnectionPrivate *_priv; \ + \ + if (G_LIKELY(NM_IS_SIMPLE_CONNECTION(_connection))) \ + _priv = _NM_SIMPLE_CONNECTION_GET_CONNECTION_PRIVATE(_connection); \ + else \ + _priv = _nm_connection_get_private_from_qdata(_connection); \ + \ + nm_assert(_priv && _priv->self == _connection); \ + \ + _priv; \ }) /*****************************************************************************/ @@ -1308,11 +1282,11 @@ _normalize_ip_config(NMConnection *self, GHashTable *parameters) && nm_setting_ip6_config_get_addr_gen_mode((NMSettingIP6Config *) s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { struct in6_addr i6_token; - char normalized[NM_UTILS_INET_ADDRSTRLEN]; + char normalized[NM_INET_ADDRSTRLEN]; if (inet_pton(AF_INET6, token, &i6_token) == 1 && _nm_utils_inet6_is_token(&i6_token)) { - _nm_utils_inet6_ntop(&i6_token, normalized); + nm_inet6_ntop(&i6_token, normalized); if (g_strcmp0(token, normalized)) { g_object_set(s_ip6, NM_SETTING_IP6_CONFIG_TOKEN, normalized, NULL); changed = TRUE; @@ -1624,6 +1598,18 @@ _normalize_bridge_port_vlan_order(NMConnection *self) } static gboolean +_normalize_ovs_port_trunks(NMConnection *self) +{ + NMSettingOvsPort *s_ovs_port; + + s_ovs_port = nm_connection_get_setting_ovs_port(self); + if (!s_ovs_port) + return FALSE; + + return _nm_setting_ovs_port_sort_trunks(s_ovs_port); +} + +static gboolean _normalize_gsm_auto_config(NMConnection *self) { NMSettingGsm *s_gsm; @@ -2015,6 +2001,7 @@ _connection_normalize(NMConnection *connection, was_modified |= _normalize_bridge_port_vlan_order(connection); was_modified |= _normalize_gsm_auto_config(connection); was_modified |= _normalize_802_1x_empty_strings(connection); + was_modified |= _normalize_ovs_port_trunks(connection); was_modified = !!was_modified; @@ -2361,35 +2348,15 @@ nm_connection_update_secrets(NMConnection *connection, return success; } -/** - * nm_connection_need_secrets: - * @connection: the #NMConnection - * @hints: (out) (element-type utf8) (allow-none) (transfer container): - * the address of a pointer to a #GPtrArray, initialized to %NULL, which on - * return points to an allocated #GPtrArray containing the property names of - * secrets of the #NMSetting which may be required; the caller owns the array - * and must free the array itself with g_ptr_array_free(), but not free its - * elements - * - * Returns the name of the first setting object in the connection which would - * need secrets to make a successful connection. The returned hints are only - * intended as a guide to what secrets may be required, because in some - * circumstances, there is no way to conclusively determine exactly which - * secrets are needed. - * - * Returns: the setting name of the #NMSetting object which has invalid or - * missing secrets - **/ -const char * -nm_connection_need_secrets(NMConnection *connection, GPtrArray **hints) +static const char * +_need_secrets(NMConnection *connection, gboolean check_rerequest, GPtrArray **hints) { NMSetting *setting_before = NULL; NMConnectionPrivate *priv; int i; - g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); - if (hints) - g_return_val_if_fail(*hints == NULL, NULL); + nm_assert(NM_IS_CONNECTION(connection)); + nm_assert(!hints || !*hints); priv = NM_CONNECTION_GET_PRIVATE(connection); @@ -2405,7 +2372,7 @@ nm_connection_need_secrets(NMConnection *connection, GPtrArray **hints) nm_assert(!setting_before || _nm_setting_compare_priority(setting_before, setting) <= 0); setting_before = setting; - secrets = _nm_setting_need_secrets(setting); + secrets = _nm_setting_need_secrets(setting, check_rerequest); if (!secrets) continue; @@ -2421,6 +2388,48 @@ nm_connection_need_secrets(NMConnection *connection, GPtrArray **hints) } /** + * nm_connection_need_secrets: + * @connection: the #NMConnection + * @hints: (out) (element-type utf8) (allow-none) (transfer container): + * the address of a pointer to a #GPtrArray, initialized to %NULL, which on + * return points to an allocated #GPtrArray containing the property names of + * secrets of the #NMSetting which may be required; the caller owns the array + * and must free the array itself with g_ptr_array_free(), but not free its + * elements + * + * Returns the name of the first setting object in the connection which would + * need secrets to make a successful connection. The returned hints are only + * intended as a guide to what secrets may be required, because in some + * circumstances, there is no way to conclusively determine exactly which + * secrets are needed. + * + * Returns: the setting name of the #NMSetting object which has invalid or + * missing secrets + **/ +const char * +nm_connection_need_secrets(NMConnection *connection, GPtrArray **hints) +{ + g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + g_return_val_if_fail(!hints || !*hints, NULL); + + return _need_secrets(connection, FALSE, hints); +} + +/** + * nm_connection_need_secrets_for_rerequest: + * @connection: the #NMConnection + * + * Returns TRUE if some secret needs to be re-requested + **/ +gboolean +nm_connection_need_secrets_for_rerequest(NMConnection *connection) +{ + g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); + + return !!_need_secrets(connection, TRUE, NULL); +} + +/** * nm_connection_clear_secrets: * @connection: the #NMConnection * @@ -2942,14 +2951,15 @@ nm_connection_dump(NMConnection *connection) void nm_connection_set_path(NMConnection *connection, const char *path) { - NMConnectionPrivate *priv; - g_return_if_fail(NM_IS_CONNECTION(connection)); - priv = NM_CONNECTION_GET_PRIVATE(connection); + nm_ref_string_reset_str(&NM_CONNECTION_GET_PRIVATE(connection)->path, path); +} - g_free(priv->path); - priv->path = g_strdup(path); +void +_nm_connection_set_path_rstr(NMConnection *connection, NMRefString *path) +{ + nm_ref_string_reset(&NM_CONNECTION_GET_PRIVATE(connection)->path, path); } /** @@ -2966,6 +2976,12 @@ nm_connection_get_path(NMConnection *connection) { g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); + return nm_ref_string_get_str(NM_CONNECTION_GET_PRIVATE(connection)->path); +} + +NMRefString * +_nm_connection_get_path_rstr(NMConnection *connection) +{ return NM_CONNECTION_GET_PRIVATE(connection)->path; } diff --git a/src/libnm-core-impl/nm-dbus-utils.c b/src/libnm-core-impl/nm-dbus-utils.c deleted file mode 100644 index c9443ff9..00000000 --- a/src/libnm-core-impl/nm-dbus-utils.c +++ /dev/null @@ -1,259 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "libnm-core-impl/nm-default-libnm-core.h" - -#include "libnm-core-intern/nm-core-internal.h" - -typedef struct { - char *signal_name; - const GVariantType *signature; -} NMDBusSignalData; - -static void -dbus_signal_data_free(gpointer data, GClosure *closure) -{ - NMDBusSignalData *sd = data; - - g_free(sd->signal_name); - g_slice_free(NMDBusSignalData, sd); -} - -static void -dbus_signal_meta_marshal(GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - NMDBusSignalData *sd = marshal_data; - const char *signal_name; - GVariant *parameters, *param; - GValue *closure_params; - gsize n_params, i; - - g_return_if_fail(n_param_values == 4); - - signal_name = g_value_get_string(¶m_values[2]); - parameters = g_value_get_variant(¶m_values[3]); - - if (strcmp(signal_name, sd->signal_name) != 0) - return; - - if (sd->signature) { - if (!g_variant_is_of_type(parameters, sd->signature)) { - g_warning("%p: got signal '%s' but parameters were of type '%s', not '%s'", - g_value_get_object(¶m_values[0]), - signal_name, - g_variant_get_type_string(parameters), - g_variant_type_peek_string(sd->signature)); - return; - } - - n_params = g_variant_n_children(parameters) + 1; - } else - n_params = 1; - - closure_params = g_new0(GValue, n_params); - g_value_init(&closure_params[0], G_TYPE_OBJECT); - g_value_copy(¶m_values[0], &closure_params[0]); - - for (i = 1; i < n_params; i++) { - param = g_variant_get_child_value(parameters, i - 1); - if (g_variant_is_of_type(param, G_VARIANT_TYPE("ay")) - || g_variant_is_of_type(param, G_VARIANT_TYPE("aay"))) { - /* g_dbus_gvariant_to_gvalue() thinks 'ay' means "non-UTF-8 NUL-terminated string" */ - g_value_init(&closure_params[i], G_TYPE_VARIANT); - g_value_set_variant(&closure_params[i], param); - } else - g_dbus_gvariant_to_gvalue(param, &closure_params[i]); - g_variant_unref(param); - } - - g_cclosure_marshal_generic(closure, NULL, n_params, closure_params, invocation_hint, NULL); - - for (i = 0; i < n_params; i++) - g_value_unset(&closure_params[i]); - g_free(closure_params); -} - -/** - * _nm_dbus_signal_connect_data: - * @proxy: a #GDBusProxy - * @signal_name: the D-Bus signal to connect to - * @signature: (allow-none): the signal's type signature (must be a tuple) - * @c_handler: the signal handler function - * @data: (allow-none): data to pass to @c_handler - * @destroy_data: (allow-none): closure destroy notify for @data - * @connect_flags: connection flags - * - * Connects to the D-Bus signal @signal_name on @proxy. @c_handler must be a - * void function whose first argument is a #GDBusProxy, followed by arguments - * for each element of @signature, ending with a #gpointer argument for @data. - * - * The argument types in @c_handler correspond to the types output by - * g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular: - * - both 16-bit and 32-bit integers are passed as #int/#guint - * - 'as' values are passed as #GStrv (char **) - * - all other array, tuple, and dict types are passed as #GVariant - * - * If @signature is %NULL, then the signal's parameters will be ignored, and - * @c_handler should take only the #GDBusProxy and #gpointer arguments. - * - * Returns: the signal handler ID, which can be used with - * g_signal_handler_remove(). Beware that because of the way the signal is - * connected, you will not be able to remove it with - * g_signal_handlers_disconnect_by_func(), although - * g_signal_handlers_disconnect_by_data() will work correctly. - */ -gulong -_nm_dbus_signal_connect_data(GDBusProxy *proxy, - const char *signal_name, - const GVariantType *signature, - GCallback c_handler, - gpointer data, - GClosureNotify destroy_data, - GConnectFlags connect_flags) -{ - NMDBusSignalData *sd; - GClosure *closure; - gboolean swapped = !!(connect_flags & G_CONNECT_SWAPPED); - gboolean after = !!(connect_flags & G_CONNECT_AFTER); - - g_return_val_if_fail(G_IS_DBUS_PROXY(proxy), 0); - g_return_val_if_fail(signal_name != NULL, 0); - g_return_val_if_fail(signature == NULL || g_variant_type_is_tuple(signature), 0); - g_return_val_if_fail(c_handler != NULL, 0); - - sd = g_slice_new(NMDBusSignalData); - sd->signal_name = g_strdup(signal_name); - sd->signature = signature; - - closure = (swapped ? g_cclosure_new_swap : g_cclosure_new)(c_handler, data, destroy_data); - g_closure_set_marshal(closure, g_cclosure_marshal_generic); - g_closure_set_meta_marshal(closure, sd, dbus_signal_meta_marshal); - g_closure_add_finalize_notifier(closure, sd, dbus_signal_data_free); - - return g_signal_connect_closure(proxy, "g-signal", closure, after); -} - -/** - * _nm_dbus_signal_connect: - * @proxy: a #GDBusProxy - * @signal_name: the D-Bus signal to connect to - * @signature: the signal's type signature (must be a tuple) - * @c_handler: the signal handler function - * @data: (allow-none): data to pass to @c_handler - * - * Simplified version of _nm_dbus_signal_connect_data() with fewer arguments. - * - * Returns: the signal handler ID, as with _nm_signal_connect_data(). - */ - -/** - * _nm_dbus_typecheck_response: - * @response: the #GVariant response to check. - * @reply_type: the expected reply type. It may be %NULL to perform no - * checking. - * @error: (allow-none): the error in case the @reply_type does not match. - * - * Returns: %TRUE, if @response is of the expected @reply_type. - */ -gboolean -_nm_dbus_typecheck_response(GVariant *response, const GVariantType *reply_type, GError **error) -{ - g_return_val_if_fail(response, FALSE); - - if (!reply_type) - return TRUE; - if (g_variant_is_of_type(response, reply_type)) - return TRUE; - - /* This is the same error code that g_dbus_connection_call() returns if - * @reply_type doesn't match. - */ - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_INVALID_ARGUMENT, - _("Method returned type '%s', but expected '%s'"), - g_variant_get_type_string(response), - g_variant_type_peek_string(reply_type)); - return FALSE; -} - -/** - * _nm_dbus_proxy_call_finish: - * @proxy: A #GDBusProxy. - * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to - * g_dbus_proxy_call(). - * @reply_type: (allow-none): the expected type of the reply, or %NULL - * @error: Return location for error or %NULL. - * - * Finishes an operation started with g_dbus_proxy_call(), as with - * g_dbus_proxy_call_finish(), except thatif @reply_type is non-%NULL, then it - * will also check that the response matches that type signature, and return - * an error if not. - * - * Returns: %NULL if @error is set. Otherwise, a #GVariant tuple with - * return values. Free with g_variant_unref(). - */ -GVariant * -_nm_dbus_proxy_call_finish(GDBusProxy *proxy, - GAsyncResult *res, - const GVariantType *reply_type, - GError **error) -{ - GVariant *variant; - - variant = g_dbus_proxy_call_finish(proxy, res, error); - if (variant && !_nm_dbus_typecheck_response(variant, reply_type, error)) - nm_clear_pointer(&variant, g_variant_unref); - return variant; -} - -GVariant * -_nm_dbus_connection_call_finish(GDBusConnection *dbus_connection, - GAsyncResult *result, - const GVariantType *reply_type, - GError **error) -{ - GVariant *variant; - - variant = g_dbus_connection_call_finish(dbus_connection, result, error); - if (variant && !_nm_dbus_typecheck_response(variant, reply_type, error)) - nm_clear_pointer(&variant, g_variant_unref); - return variant; -} - -/** - * _nm_dbus_error_has_name: - * @error: (allow-none): a #GError, or %NULL - * @dbus_error_name: a D-Bus error name - * - * Checks if @error is set and corresponds to the D-Bus error @dbus_error_name. - * - * This should only be used for "foreign" D-Bus errors (eg, errors - * from BlueZ or wpa_supplicant). All NetworkManager D-Bus errors - * should be properly mapped by gdbus to one of the domains/codes in - * nm-errors.h. - * - * Returns: %TRUE or %FALSE - */ -gboolean -_nm_dbus_error_has_name(GError *error, const char *dbus_error_name) -{ - gboolean has_name = FALSE; - - if (error && g_dbus_error_is_remote_error(error)) { - char *error_name; - - error_name = g_dbus_error_get_remote_error(error); - has_name = !g_strcmp0(error_name, dbus_error_name); - g_free(error_name); - } - - return has_name; -} diff --git a/src/libnm-core-impl/nm-default-libnm-core.h b/src/libnm-core-impl/nm-default-libnm-core.h index 0f27f82d..013df67d 100644 --- a/src/libnm-core-impl/nm-default-libnm-core.h +++ b/src/libnm-core-impl/nm-default-libnm-core.h @@ -16,6 +16,7 @@ /*****************************************************************************/ #include "nm-version.h" +#include "nm-errors.h" /*****************************************************************************/ diff --git a/src/libnm-core-impl/nm-keyfile.c b/src/libnm-core-impl/nm-keyfile.c index 6ee68b5c..9a6ffc6f 100644 --- a/src/libnm-core-impl/nm-keyfile.c +++ b/src/libnm-core-impl/nm-keyfile.c @@ -28,12 +28,14 @@ #include "nm-setting-private.h" #include "nm-setting-user.h" #include "nm-setting-ovs-external-ids.h" +#include "nm-setting-ovs-other-config.h" #include "libnm-core-intern/nm-keyfile-utils.h" #define ETHERNET_S390_OPTIONS_GROUP_NAME "ethernet-s390-options" -#define OVS_EXTERNAL_IDS_DATA_PREFIX "data." +/* used for "ovs-external-ids.data" and "ovs-other-config.data". */ +#define STRDICT_DATA_PREFIX "data." /*****************************************************************************/ @@ -397,7 +399,7 @@ build_route(KeyfileReaderInfo *info, /* Next hop */ if (gateway_str && gateway_str[0]) { - if (!nm_utils_ipaddr_is_valid(family, gateway_str)) { + if (!nm_inet_is_valid(family, gateway_str)) { /* Try workaround for routes written by broken keyfile writer. * Due to bug bgo#719851, an older version of writer would have * written "a:b:c:d::/plen,metric" if the gateway was ::, instead @@ -1060,23 +1062,29 @@ ip_routing_rule_parser_full(KeyfileReaderInfo *info, } static void -_parser_full_ovs_external_ids_data(KeyfileReaderInfo *info, - const NMMetaSettingInfo *setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty *pip, - NMSetting *setting) +_parser_full_strdict_data(KeyfileReaderInfo *info, + const NMMetaSettingInfo *setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty *pip, + NMSetting *setting) { - const char *setting_name = NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME; - gs_strfreev char **keys = NULL; + gs_strfreev char **keys = NULL; gsize n_keys; gsize i; + gboolean is_exid; - nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting)); - nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)); - nm_assert(nm_streq(setting_name, setting_info->setting_name)); - nm_assert(nm_streq(setting_name, nm_setting_get_name(setting))); + if (NM_IS_SETTING_OVS_EXTERNAL_IDS(setting)) { + nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)); + is_exid = TRUE; + } else { + nm_assert(NM_IS_SETTING_OVS_OTHER_CONFIG(setting)); + nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_OTHER_CONFIG_DATA)); + is_exid = FALSE; + } - keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_name, &n_keys, NULL); + nm_assert(nm_streq(setting_info->setting_name, nm_setting_get_name(setting))); + + keys = nm_keyfile_plugin_kf_get_keys(info->keyfile, setting_info->setting_name, &n_keys, NULL); for (i = 0; i < n_keys; i++) { const char *key = keys[i]; @@ -1084,16 +1092,20 @@ _parser_full_ovs_external_ids_data(KeyfileReaderInfo *info, gs_free char *value = NULL; const char *name; - if (!NM_STR_HAS_PREFIX(key, OVS_EXTERNAL_IDS_DATA_PREFIX)) + if (!NM_STR_HAS_PREFIX(key, STRDICT_DATA_PREFIX)) continue; - value = nm_keyfile_plugin_kf_get_string(info->keyfile, setting_name, key, NULL); + value = + nm_keyfile_plugin_kf_get_string(info->keyfile, setting_info->setting_name, key, NULL); if (!value) continue; - name = &key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)]; + name = &key[NM_STRLEN(STRDICT_DATA_PREFIX)]; name = nm_keyfile_key_decode(name, &name_to_free); - nm_setting_ovs_external_ids_set_data(NM_SETTING_OVS_EXTERNAL_IDS(setting), name, value); + if (is_exid) + nm_setting_ovs_external_ids_set_data(NM_SETTING_OVS_EXTERNAL_IDS(setting), name, value); + else + nm_setting_ovs_other_config_set_data(NM_SETTING_OVS_OTHER_CONFIG(setting), name, value); } } @@ -1102,7 +1114,9 @@ ip_dns_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) { int addr_family; gs_strfreev char **list = NULL; - gsize i, n, length; + gsize length; + gsize n; + gsize i; nm_assert(NM_IS_SETTING_IP4_CONFIG(setting) || NM_IS_SETTING_IP6_CONFIG(setting)); @@ -1115,13 +1129,10 @@ ip_dns_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) if (length == 0) return; - addr_family = NM_IS_SETTING_IP4_CONFIG(setting) ? AF_INET : AF_INET6; - - n = 0; - for (i = 0; i < length; i++) { - NMIPAddr addr; + addr_family = NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting); - if (inet_pton(addr_family, list[i], &addr) <= 0) { + for (i = 0, n = 0; i < length; i++) { + if (!nm_utils_dnsname_parse(addr_family, list[i], NULL, NULL, NULL)) { if (!read_handle_warn(info, key, key, @@ -2009,6 +2020,44 @@ bridge_vlan_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) } static void +range_list_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) +{ + gs_unref_ptrarray GPtrArray *ranges = NULL; + gs_free char *value = NULL; + gs_free const char **strv = NULL; + const char *const *iter; + GError *local = NULL; + NMRange *range; + + value = nm_keyfile_plugin_kf_get_string(info->keyfile, nm_setting_get_name(setting), key, NULL); + if (!value || !value[0]) + return; + + ranges = g_ptr_array_new_with_free_func((GDestroyNotify) nm_range_unref); + + strv = nm_utils_escaped_tokens_split(value, ","); + if (strv) { + for (iter = strv; *iter; iter++) { + range = nm_range_from_str(*iter, &local); + if (!range) { + read_handle_warn(info, + key, + key, + NM_KEYFILE_WARN_SEVERITY_WARN, + "invalid range: %s", + local->message); + g_clear_error(&local); + continue; + } + g_ptr_array_add(ranges, range); + } + } + + if (ranges->len > 0) + g_object_set(setting, key, ranges, NULL); +} + +static void qdisc_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key) { const char *setting_name = nm_setting_get_name(setting); @@ -2173,7 +2222,7 @@ write_array_of_uint(GKeyFile *file, NMSetting *setting, const char *key, const G nm_keyfile_plugin_kf_set_integer_list_uint(file, nm_setting_get_name(setting), key, - (const guint *) array->data, + &nm_g_array_first(array, const guint), array->len); } @@ -2346,6 +2395,33 @@ bridge_vlan_writer(KeyfileWriterInfo *info, } static void +range_list_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, const GValue *value) +{ + GPtrArray *ranges; + + ranges = g_value_get_boxed(value); + if (ranges && ranges->len > 0) { + const guint string_initial_size = ranges->len * 10u; + nm_auto_str_buf NMStrBuf string = NM_STR_BUF_INIT(string_initial_size, FALSE); + guint i; + + for (i = 0; i < ranges->len; i++) { + gs_free char *range_str = NULL; + + range_str = nm_range_to_str(ranges->pdata[i]); + if (i > 0) + nm_str_buf_append_c(&string, ','); + nm_utils_escaped_tokens_escape_strbuf_assert(range_str, ",", &string); + } + + nm_keyfile_plugin_kf_set_string(info->keyfile, + nm_setting_get_name(setting), + key, + nm_str_buf_get_str(&string)); + } +} + +static void wired_s390_options_parser_full(KeyfileReaderInfo *info, const NMMetaSettingInfo *setting_info, const NMSettInfoProperty *property_info, @@ -2505,24 +2581,32 @@ tfilter_writer(KeyfileWriterInfo *info, NMSetting *setting, const char *key, con } static void -_writer_full_ovs_external_ids_data(KeyfileWriterInfo *info, - const NMMetaSettingInfo *setting_info, - const NMSettInfoProperty *property_info, - const ParseInfoProperty *pip, - NMSetting *setting) +_writer_full_strdict_data(KeyfileWriterInfo *info, + const NMMetaSettingInfo *setting_info, + const NMSettInfoProperty *property_info, + const ParseInfoProperty *pip, + NMSetting *setting) { GHashTable *hash; NMUtilsNamedValue data_static[300u / sizeof(NMUtilsNamedValue)]; gs_free NMUtilsNamedValue *data_free = NULL; const NMUtilsNamedValue *data; guint data_len; - char full_key_static[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX) + 300u]; + char full_key_static[NM_STRLEN(STRDICT_DATA_PREFIX) + 300u]; guint i; + gboolean is_exid; - nm_assert(NM_IS_SETTING_OVS_EXTERNAL_IDS(setting)); - nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)); + if (NM_IS_SETTING_OVS_EXTERNAL_IDS(setting)) { + nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_EXTERNAL_IDS_DATA)); + is_exid = TRUE; + } else { + nm_assert(NM_IS_SETTING_OVS_OTHER_CONFIG(setting)); + nm_assert(nm_streq(property_info->name, NM_SETTING_OVS_OTHER_CONFIG_DATA)); + is_exid = FALSE; + } - hash = _nm_setting_ovs_external_ids_get_data(NM_SETTING_OVS_EXTERNAL_IDS(setting)); + hash = is_exid ? _nm_setting_ovs_external_ids_get_data(NM_SETTING_OVS_EXTERNAL_IDS(setting)) + : _nm_setting_ovs_other_config_get_data(NM_SETTING_OVS_OTHER_CONFIG(setting)); if (!hash) return; @@ -2530,7 +2614,7 @@ _writer_full_ovs_external_ids_data(KeyfileWriterInfo *info, if (data_len == 0) return; - memcpy(full_key_static, OVS_EXTERNAL_IDS_DATA_PREFIX, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)); + memcpy(full_key_static, STRDICT_DATA_PREFIX, NM_STRLEN(STRDICT_DATA_PREFIX)); for (i = 0; i < data_len; i++) { const char *key = data[i].name; @@ -2544,15 +2628,16 @@ _writer_full_ovs_external_ids_data(KeyfileWriterInfo *info, escaped_key = nm_keyfile_key_encode(key, &escaped_key_to_free); len = strlen(escaped_key) + 1u; - if (len >= G_N_ELEMENTS(full_key_static) - NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)) { - full_key_free = g_new(char, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX) + len); + if (len >= G_N_ELEMENTS(full_key_static) - NM_STRLEN(STRDICT_DATA_PREFIX)) { + full_key_free = g_new(char, NM_STRLEN(STRDICT_DATA_PREFIX) + len); full_key = full_key_free; - memcpy(full_key, OVS_EXTERNAL_IDS_DATA_PREFIX, NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)); + memcpy(full_key, STRDICT_DATA_PREFIX, NM_STRLEN(STRDICT_DATA_PREFIX)); } - memcpy(&full_key[NM_STRLEN(OVS_EXTERNAL_IDS_DATA_PREFIX)], escaped_key, len); + memcpy(&full_key[NM_STRLEN(STRDICT_DATA_PREFIX)], escaped_key, len); nm_keyfile_plugin_kf_set_string(info->keyfile, - NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME, + is_exid ? NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME + : NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME, full_key, val); } @@ -2935,6 +3020,12 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { .parser = bridge_vlan_parser, .writer = bridge_vlan_writer, ), ), ), PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_OVS_PORT, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_OVS_PORT_TRUNKS, + .parser_no_check_key = TRUE, + .parser = range_list_parser, + .writer = range_list_writer, ), ), ), + PARSE_INFO_SETTING( NM_META_SETTING_TYPE_BRIDGE_PORT, PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_BRIDGE_PORT_VLANS, .parser_no_check_key = TRUE, @@ -3007,10 +3098,18 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_OVS_EXTERNAL_IDS_DATA, .parser_no_check_key = TRUE, - .parser_full = _parser_full_ovs_external_ids_data, - .writer_full = _writer_full_ovs_external_ids_data, - .has_parser_full = TRUE, - .has_writer_full = TRUE, ), ), ), + .parser_full = _parser_full_strdict_data, + .writer_full = _writer_full_strdict_data, + .has_parser_full = TRUE, + .has_writer_full = TRUE, ), ), ), + PARSE_INFO_SETTING( + NM_META_SETTING_TYPE_OVS_OTHER_CONFIG, + PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_OVS_OTHER_CONFIG_DATA, + .parser_no_check_key = TRUE, + .parser_full = _parser_full_strdict_data, + .writer_full = _writer_full_strdict_data, + .has_parser_full = TRUE, + .has_writer_full = TRUE, ), ), ), PARSE_INFO_SETTING(NM_META_SETTING_TYPE_SERIAL, PARSE_INFO_PROPERTIES(PARSE_INFO_PROPERTY(NM_SETTING_SERIAL_PARITY, .parser = parity_parser, ), ), ), @@ -3188,11 +3287,11 @@ _parse_info_find(NMSetting *setting, G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(ParseInfoProperty, property_name) == 0); - idx = nm_utils_ptrarray_find_binary_search((gconstpointer *) pis->properties, - NM_PTRARRAY_LEN(pis->properties), - &property_name, - nm_strcmp_p_with_data, - NULL); + idx = nm_ptrarray_find_bsearch((gconstpointer *) pis->properties, + NM_PTRARRAY_LEN(pis->properties), + &property_name, + nm_strcmp_p_with_data, + NULL); if (idx >= 0) pip = pis->properties[idx]; } @@ -3692,7 +3791,7 @@ _read_setting_wireguard_peer(KeyfileReaderInfo *info) gsize i; for (i = 0; i < n_sa; i++) { - if (!nm_utils_parse_inaddr_prefix_bin(AF_UNSPEC, sa[i], NULL, NULL, NULL)) { + if (!nm_inet_parse_with_prefix_bin(AF_UNSPEC, sa[i], NULL, NULL, NULL)) { has_error = TRUE; continue; } @@ -3800,7 +3899,7 @@ nm_keyfile_read_ensure_uuid(NMConnection *connection, const char *fallback_uuid_ if (nm_setting_connection_get_uuid(s_con)) return FALSE; - hashed_uuid = nm_uuid_generate_from_strings("keyfile", fallback_uuid_seed, NULL); + hashed_uuid = nm_uuid_generate_from_strings_old("keyfile", fallback_uuid_seed); g_object_set(s_con, NM_SETTING_CONNECTION_UUID, hashed_uuid, NULL); return TRUE; } diff --git a/src/libnm-core-impl/nm-meta-setting-base-impl.c b/src/libnm-core-impl/nm-meta-setting-base-impl.c index 69daa76c..19082671 100644 --- a/src/libnm-core-impl/nm-meta-setting-base-impl.c +++ b/src/libnm-core-impl/nm-meta-setting-base-impl.c @@ -3,6 +3,8 @@ * Copyright (C) 2017 - 2018 Red Hat, Inc. */ +#define NM_WANT_NM_ARRAY_FIND_BSEARCH_INLINE + #include "libnm-glib-aux/nm-default-glib-i18n-lib.h" #include "nm-meta-setting-base.h" @@ -32,14 +34,16 @@ #include "nm-setting-ip-tunnel.h" #include "nm-setting-ip4-config.h" #include "nm-setting-ip6-config.h" +#include "nm-setting-loopback.h" #include "nm-setting-macsec.h" #include "nm-setting-macvlan.h" #include "nm-setting-match.h" #include "nm-setting-olpc-mesh.h" #include "nm-setting-ovs-bridge.h" -#include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-dpdk.h" #include "nm-setting-ovs-external-ids.h" +#include "nm-setting-ovs-interface.h" +#include "nm-setting-ovs-other-config.h" #include "nm-setting-ovs-patch.h" #include "nm-setting-ovs-port.h" #include "nm-setting-ppp.h" @@ -358,6 +362,13 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = { .setting_name = NM_SETTING_IP_TUNNEL_SETTING_NAME, .get_setting_gtype = nm_setting_ip_tunnel_get_type, }, + [NM_META_SETTING_TYPE_LOOPBACK] = + { + .meta_type = NM_META_SETTING_TYPE_LOOPBACK, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_LOOPBACK_SETTING_NAME, + .get_setting_gtype = nm_setting_loopback_get_type, + }, [NM_META_SETTING_TYPE_MACSEC] = { .meta_type = NM_META_SETTING_TYPE_MACSEC, @@ -400,6 +411,13 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = { .setting_name = NM_SETTING_OVS_DPDK_SETTING_NAME, .get_setting_gtype = nm_setting_ovs_dpdk_get_type, }, + [NM_META_SETTING_TYPE_OVS_OTHER_CONFIG] = + { + .meta_type = NM_META_SETTING_TYPE_OVS_OTHER_CONFIG, + .setting_priority = NM_SETTING_PRIORITY_AUX, + .setting_name = NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME, + .get_setting_gtype = nm_setting_ovs_other_config_get_type, + }, [NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS] = { .meta_type = NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, @@ -608,6 +626,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = { NM_META_SETTING_TYPE_GSM, NM_META_SETTING_TYPE_INFINIBAND, NM_META_SETTING_TYPE_IP_TUNNEL, + NM_META_SETTING_TYPE_LOOPBACK, NM_META_SETTING_TYPE_MACSEC, NM_META_SETTING_TYPE_MACVLAN, NM_META_SETTING_TYPE_OVS_BRIDGE, @@ -643,6 +662,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = { NM_META_SETTING_TYPE_ETHTOOL, NM_META_SETTING_TYPE_MATCH, NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS, + NM_META_SETTING_TYPE_OVS_OTHER_CONFIG, NM_META_SETTING_TYPE_PPP, NM_META_SETTING_TYPE_PPPOE, NM_META_SETTING_TYPE_TEAM_PORT, @@ -693,29 +713,31 @@ nm_meta_setting_infos_by_name(const char *name) } G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMMetaSettingInfo, setting_name) == 0); - idx = nm_utils_array_find_binary_search(nm_meta_setting_infos, - sizeof(NMMetaSettingInfo), - _NM_META_SETTING_TYPE_NUM, - &name, - nm_strcmp_p_with_data, - NULL); + idx = nm_array_find_bsearch(nm_meta_setting_infos, + _NM_META_SETTING_TYPE_NUM, + sizeof(NMMetaSettingInfo), + &name, + nm_strcmp_p_with_data, + NULL); return idx >= 0 ? &nm_meta_setting_infos[idx] : NULL; } -const NMMetaSettingInfo * -nm_meta_setting_infos_by_gtype(GType gtype) -{ +/*****************************************************************************/ + #if _NM_META_SETTING_BASE_IMPL_LIBNM +static const NMMetaSettingInfo * +_infos_by_gtype_from_class(GType gtype) +{ nm_auto_unref_gtypeclass GTypeClass *gtypeclass_unref = NULL; GTypeClass *gtypeclass; NMSettingClass *klass; if (!g_type_is_a(gtype, NM_TYPE_SETTING)) - goto out_none; + return NULL; gtypeclass = g_type_class_peek(gtype); - if (!gtypeclass) + if (G_UNLIKELY(!gtypeclass)) gtypeclass = gtypeclass_unref = g_type_class_ref(gtype); nm_assert(NM_IS_SETTING_CLASS(gtypeclass)); @@ -723,38 +745,112 @@ nm_meta_setting_infos_by_gtype(GType gtype) klass = (NMSettingClass *) gtypeclass; if (!klass->setting_info) - goto out_none; + return NULL; nm_assert(klass->setting_info->get_setting_gtype); nm_assert(klass->setting_info->get_setting_gtype() == gtype); - return klass->setting_info; +} +#endif -out_none: - - if (NM_MORE_ASSERTS > 10) { - int i; - - /* this might hint to a bug, but it would be expected for NM_TYPE_SETTING - * and NM_TYPE_SETTING_IP_CONFIG. - * - * Assert that we didn't lookup for a gtype, which we would expect to find. - * An assertion failure here, hints to a bug in nm_setting_*_class_init(). - */ - for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) - nm_assert(nm_meta_setting_infos[i].get_setting_gtype() != gtype); - } - - return NULL; -#else - guint i; +static const NMMetaSettingInfo * +_infos_by_gtype_search(GType gtype) +{ + int i; - for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { + for (i = 0; i < (int) _NM_META_SETTING_TYPE_NUM; i++) { if (nm_meta_setting_infos[i].get_setting_gtype() == gtype) return &nm_meta_setting_infos[i]; } return NULL; +} + +typedef struct { + GType gtype; + const NMMetaSettingInfo *setting_info; +} LookupData; + +_nm_always_inline static inline int +_lookup_data_cmp(gconstpointer ptr_a, gconstpointer ptr_b, gpointer user_data) +{ + const GType *const a = ptr_a; + const GType *const b = ptr_b; + + nm_assert(a); + nm_assert(b); + nm_assert(a != b); + + NM_CMP_DIRECT(*a, *b); + return 0; +} + +static const NMMetaSettingInfo * +_infos_by_gtype_binary_search(GType gtype) +{ + static LookupData static_array[_NM_META_SETTING_TYPE_NUM]; + static const LookupData *static_ptr = NULL; + const LookupData *ptr; + gssize idx; + +again: + ptr = g_atomic_pointer_get(&static_ptr); + if (G_UNLIKELY(!ptr)) { + static gsize g_lock = 0; + int i; + + if (!g_once_init_enter(&g_lock)) + goto again; + + for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { + const NMMetaSettingInfo *m = &nm_meta_setting_infos[i]; + + static_array[i] = (LookupData){ + .gtype = m->get_setting_gtype(), + .setting_info = m, + }; + } + + g_qsort_with_data(static_array, + _NM_META_SETTING_TYPE_NUM, + sizeof(static_array[0]), + _lookup_data_cmp, + NULL); + + ptr = static_array; + g_atomic_pointer_set(&static_ptr, ptr); + + g_once_init_leave(&g_lock, 1); + } + + idx = nm_array_find_bsearch_inline(ptr, + _NM_META_SETTING_TYPE_NUM, + sizeof(ptr[0]), + >ype, + _lookup_data_cmp, + NULL); + if (idx < 0) + return NULL; + + return ptr[idx].setting_info; +} + +const NMMetaSettingInfo * +nm_meta_setting_infos_by_gtype(GType gtype) +{ + const NMMetaSettingInfo *setting_info; + +#if _NM_META_SETTING_BASE_IMPL_LIBNM + setting_info = _infos_by_gtype_from_class(gtype); +#else + setting_info = _infos_by_gtype_binary_search(gtype); #endif + + if (NM_MORE_ASSERTS > 20) { + nm_assert(setting_info == _infos_by_gtype_search(gtype)); + nm_assert(setting_info == _infos_by_gtype_binary_search(gtype)); + } + + return setting_info; } /*****************************************************************************/ diff --git a/src/libnm-core-impl/nm-setting-6lowpan.c b/src/libnm-core-impl/nm-setting-6lowpan.c index 21b3dbb9..e0b5d650 100644 --- a/src/libnm-core-impl/nm-setting-6lowpan.c +++ b/src/libnm-core-impl/nm-setting-6lowpan.c @@ -53,7 +53,7 @@ G_DEFINE_TYPE(NMSetting6Lowpan, nm_setting_6lowpan, NM_TYPE_SETTING) * * Returns: the #NMSetting6Lowpan:parent property of the setting * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ const char * nm_setting_6lowpan_get_parent(NMSetting6Lowpan *setting) @@ -141,7 +141,7 @@ nm_setting_6lowpan_init(NMSetting6Lowpan *setting) * * Returns: (transfer full): the new empty #NMSetting6Lowpan object * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ NMSetting * nm_setting_6lowpan_new(void) diff --git a/src/libnm-core-impl/nm-setting-8021x.c b/src/libnm-core-impl/nm-setting-8021x.c index fd9a0961..1bc4de9d 100644 --- a/src/libnm-core-impl/nm-setting-8021x.c +++ b/src/libnm-core-impl/nm-setting-8021x.c @@ -67,7 +67,10 @@ _crypto_format_to_ck(NMCryptoFileFormat format) /*****************************************************************************/ -typedef void (*EAPMethodNeedSecretsFunc)(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2); +typedef void (*EAPMethodNeedSecretsFunc)(NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2, + gboolean check_rerequest); typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self, gboolean phase2, GError **error); @@ -1601,7 +1604,7 @@ nm_setting_802_1x_get_phase2_ca_cert_path(NMSetting8021x *setting) * nm_setting_802_1x_get_phase2_ca_cert_blob() and * nm_setting_802_1x_get_phase2_ca_cert_path(). * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * Currently, it's limited to PKCS#<!-- -->11 URIs ('pkcs11' scheme as defined by RFC * 7512), but may be extended to other schemes in future (such as 'file' URIs * for local files and 'data' URIs for inline certificate data). * @@ -1937,7 +1940,7 @@ nm_setting_802_1x_get_phase2_client_cert_path(NMSetting8021x *setting) * nm_setting_802_1x_get_phase2_ca_cert_blob() and * nm_setting_802_1x_get_phase2_ca_cert_path(). * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * Currently, it's limited to PKCS#<!-- -->11 URIs ('pkcs11' scheme as defined by RFC * 7512), but may be extended to other schemes in future (such as 'file' URIs * for local files and 'data' URIs for inline certificate data). * @@ -2173,7 +2176,7 @@ nm_setting_802_1x_get_private_key_path(NMSetting8021x *setting) * nm_setting_802_1x_get_private_key_blob() and * nm_setting_802_1x_get_private_key_path(). * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * Currently, it's limited to PKCS#<!-- -->11 URIs ('pkcs11' scheme as defined by RFC * 7512), but may be extended to other schemes in future (such as 'file' URIs * for local files and 'data' URIs for inline certificate data). * @@ -2376,7 +2379,7 @@ nm_setting_802_1x_get_phase2_private_key_path(NMSetting8021x *setting) * nm_setting_802_1x_get_phase2_private_key_blob() and * nm_setting_802_1x_get_phase2_private_key_path(). * - * Currently, it's limited to PKCS#11 URIs ('pkcs11' scheme as defined by RFC + * Currently, it's limited to PKCS#<!-- -->11 URIs ('pkcs11' scheme as defined by RFC * 7512), but may be extended to other schemes in future (such as 'file' URIs * for local files and 'data' URIs for inline certificate data). * @@ -2500,32 +2503,45 @@ nm_setting_802_1x_get_optional(NMSetting8021x *setting) /*****************************************************************************/ static void -need_secrets_password(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) +need_secrets_password(NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2, + gboolean check_rerequest) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - if (nm_str_is_empty(priv->password) - && (!priv->password_raw || !g_bytes_get_size(priv->password_raw))) { + if (check_rerequest + || (nm_str_is_empty(priv->password) + && (!priv->password_raw || !g_bytes_get_size(priv->password_raw)))) { g_ptr_array_add(secrets, NM_SETTING_802_1X_PASSWORD); g_ptr_array_add(secrets, NM_SETTING_802_1X_PASSWORD_RAW); } } static void -need_secrets_sim(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) +need_secrets_sim(NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2, + gboolean check_rerequest) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); - if (nm_str_is_empty(priv->pin)) + if (check_rerequest || nm_str_is_empty(priv->pin)) g_ptr_array_add(secrets, NM_SETTING_802_1X_PIN); } static void -need_secrets_tls(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) +need_secrets_tls(NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2, + gboolean check_rerequest) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); NMSetting8021xCKScheme scheme; + /* If check_rerequest is TRUE do not return secrets, unless missing. + * This secret cannot be wrong. */ + if (!NM_FLAGS_HAS(phase2 ? priv->phase2_private_key_password_flags : priv->private_key_password_flags, NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { @@ -2719,7 +2735,10 @@ verify_ttls(NMSetting8021x *self, gboolean phase2, GError **error) } static void -need_secrets_phase2(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) +need_secrets_phase2(NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2, + gboolean check_rerequest) { NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); char *method = NULL; @@ -2740,7 +2759,7 @@ need_secrets_phase2(NMSetting8021x *self, GPtrArray *secrets, gboolean phase2) if (!eap_methods_table[i].ns_func) continue; if (nm_streq(eap_methods_table[i].method, method)) { - (*eap_methods_table[i].ns_func)(self, secrets, TRUE); + (*eap_methods_table[i].ns_func)(self, secrets, TRUE, check_rerequest); break; } } @@ -2885,10 +2904,35 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } if (NM_FLAGS_ANY(priv->phase1_auth_flags, ~((guint32) NM_SETTING_802_1X_AUTH_FLAGS_ALL))) { - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("invalid auth flags")); + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid auth flags: '%d' contains unknown flags"), + priv->phase1_auth_flags); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE1_AUTH_FLAGS); + return FALSE; + } + + if (NM_FLAGS_ALL(priv->phase1_auth_flags, + NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_ENABLE + | NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_DISABLE) + || NM_FLAGS_ALL(priv->phase1_auth_flags, + NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_ENABLE + | NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_DISABLE) + || NM_FLAGS_ALL(priv->phase1_auth_flags, + NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_2_ENABLE + | NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_2_DISABLE) + || NM_FLAGS_ALL(priv->phase1_auth_flags, + NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_3_ENABLE + | NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_3_DISABLE)) { + g_set_error_literal( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid auth flags: both enable and disable are set for the same TLS version")); g_prefix_error(error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, @@ -3030,7 +3074,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) /*****************************************************************************/ static GPtrArray * -need_secrets(NMSetting *setting) +need_secrets(NMSetting *setting, gboolean check_rerequest) { NMSetting8021x *self = NM_SETTING_802_1X(setting); NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE(self); @@ -3049,7 +3093,7 @@ need_secrets(NMSetting *setting) if (eap_methods_table[i].ns_func == NULL) continue; if (!strcmp(eap_methods_table[i].method, method)) { - (*eap_methods_table[i].ns_func)(self, secrets, FALSE); + (*eap_methods_table[i].ns_func)(self, secrets, FALSE, check_rerequest); /* Only break out of the outer loop if this EAP method * needed secrets. @@ -3296,9 +3340,6 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Since: 1.8 **/ - /* ---ifcfg-rh--- - * ---end--- - */ _nm_setting_property_define_direct_string(properties_override, obj_properties, NM_SETTING_802_1X_CA_CERT_PASSWORD, @@ -3314,9 +3355,6 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Since: 1.8 **/ - /* ---ifcfg-rh--- - * ---end--- - */ _nm_setting_property_define_direct_secret_flags(properties_override, obj_properties, NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS, @@ -3353,9 +3391,10 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Substring to be matched against the subject of the certificate presented * by the authentication server. When unset, no verification of the - * authentication server certificate's subject is performed. This property - * provides little security, if any, and its use is deprecated in favor of - * NMSetting8021x:domain-suffix-match. + * authentication server certificate's subject is performed. This property + * provides little security, if any, and should not be used. + * + * Deprecated: 1.2: Use #NMSetting8021x:phase2-domain-suffix-match instead. **/ /* ---ifcfg-rh--- * property: subject-match @@ -3370,7 +3409,8 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) PROP_SUBJECT_MATCH, NM_SETTING_PARAM_NONE, NMSetting8021xPrivate, - subject_match); + subject_match, + .is_deprecated = TRUE, ); /** * NMSetting8021x:altsubject-matches: @@ -3486,9 +3526,6 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Since: 1.8 **/ - /* ---ifcfg-rh--- - * ---end--- - */ _nm_setting_property_define_direct_string(properties_override, obj_properties, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, @@ -3504,9 +3541,6 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Since: 1.8 **/ - /* ---ifcfg-rh--- - * ---end--- - */ _nm_setting_property_define_direct_secret_flags(properties_override, obj_properties, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS, @@ -3594,9 +3628,10 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Specifies authentication flags to use in "phase 1" outer * authentication using #NMSetting8021xAuthFlags options. - * The individual TLS versions can be explicitly disabled. If a certain - * TLS disable flag is not set, it is up to the supplicant to allow - * or forbid it. The TLS options map to tls_disable_tlsv1_x settings. + * The individual TLS versions can be explicitly disabled. TLS time checks + * can be also disabled. If a certain TLS disable flag is not + * set, it is up to the supplicant to allow or forbid it. The TLS options + * map to tls_disable_tlsv1_x and tls_disable_time_checks settings. * See the wpa_supplicant documentation for more details. * * Since: 1.8 @@ -3718,9 +3753,6 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Since: 1.8 **/ - /* ---ifcfg-rh--- - * ---end--- - */ _nm_setting_property_define_direct_string(properties_override, obj_properties, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, @@ -3736,9 +3768,6 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Since: 1.8 **/ - /* ---ifcfg-rh--- - * ---end--- - */ _nm_setting_property_define_direct_secret_flags(properties_override, obj_properties, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS, @@ -3776,9 +3805,10 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * Substring to be matched against the subject of the certificate presented * by the authentication server during the inner "phase 2" * authentication. When unset, no verification of the authentication server - * certificate's subject is performed. This property provides little security, - * if any, and its use is deprecated in favor of - * NMSetting8021x:phase2-domain-suffix-match. + * certificate's subject is performed. This property provides little security, + * if any, and should not be used. + * + * Deprecated: 1.2: Use #NMSetting8021x:phase2-domain-suffix-match instead. **/ /* ---ifcfg-rh--- * property: phase2-subject-match @@ -3793,7 +3823,8 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) PROP_PHASE2_SUBJECT_MATCH, NM_SETTING_PARAM_NONE, NMSetting8021xPrivate, - phase2_subject_match); + phase2_subject_match, + .is_deprecated = TRUE, ); /** * NMSetting8021x:phase2-altsubject-matches: @@ -3913,9 +3944,6 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Since: 1.8 **/ - /* ---ifcfg-rh--- - * ---end--- - */ _nm_setting_property_define_direct_string(properties_override, obj_properties, NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, @@ -3931,9 +3959,6 @@ nm_setting_802_1x_class_init(NMSetting8021xClass *klass) * * Since: 1.8 **/ - /* ---ifcfg-rh--- - * ---end--- - */ _nm_setting_property_define_direct_secret_flags( properties_override, obj_properties, diff --git a/src/libnm-core-impl/nm-setting-adsl.c b/src/libnm-core-impl/nm-setting-adsl.c index 88606b69..ca291389 100644 --- a/src/libnm-core-impl/nm-setting-adsl.c +++ b/src/libnm-core-impl/nm-setting-adsl.c @@ -225,12 +225,12 @@ verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) } static GPtrArray * -need_secrets(NMSetting *setting) +need_secrets(NMSetting *setting, gboolean check_rerequest) { NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE(setting); GPtrArray *secrets = NULL; - if (priv->password && *priv->password) + if (!check_rerequest && priv->password && *priv->password) return NULL; if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { diff --git a/src/libnm-core-impl/nm-setting-bond.c b/src/libnm-core-impl/nm-setting-bond.c index 18b6fefb..54030e0b 100644 --- a/src/libnm-core-impl/nm-setting-bond.c +++ b/src/libnm-core-impl/nm-setting-bond.c @@ -70,6 +70,7 @@ static const char *const valid_options_lst[] = { NM_SETTING_BOND_OPTION_ARP_INTERVAL, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, NM_SETTING_BOND_OPTION_ARP_VALIDATE, + NM_SETTING_BOND_OPTION_BALANCE_SLB, NM_SETTING_BOND_OPTION_PRIMARY, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, @@ -195,6 +196,7 @@ static NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE( {NM_SETTING_BOND_OPTION_ARP_IP_TARGET, {"", NM_BOND_OPTION_TYPE_IP}}, {NM_SETTING_BOND_OPTION_ARP_VALIDATE, {"none", NM_BOND_OPTION_TYPE_BOTH, 0, 6, _option_default_strv_arp_validate}}, + {NM_SETTING_BOND_OPTION_BALANCE_SLB, {"0", NM_BOND_OPTION_TYPE_INT, 0, 1}}, {NM_SETTING_BOND_OPTION_DOWNDELAY, {"0", NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT}}, {NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, {"none", NM_BOND_OPTION_TYPE_BOTH, 0, 2, _option_default_strv_fail_over_mac}}, @@ -344,6 +346,17 @@ _bond_get_option_normalized(NMSettingBond *self, const char *option, gboolean ge value = _bond_get_option(self, NM_SETTING_BOND_OPTION_PRIMARY); if (!value) value = _bond_get_option(self, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE); + } else if (nm_streq(option, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY)) { + if (_nm_utils_ascii_str_to_int64( + _bond_get_option(self, NM_SETTING_BOND_OPTION_BALANCE_SLB), + 10, + 0, + 1, + -1) + == 1) { + /* balance-slb implies vlan+srcmac */ + return "5"; + } } else value = _bond_get_option(self, option); @@ -506,7 +519,7 @@ validate_ip(const char *name, const char *value, GError **error) return FALSE; } for (i = 0; addrs[i]; i++) { - if (!nm_utils_parse_inaddr_bin(AF_INET, addrs[i], NULL, NULL)) { + if (!nm_inet_parse_bin(AF_INET, addrs[i], NULL, NULL)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -588,7 +601,7 @@ handle_error: /** * nm_setting_bond_validate_option: * @name: the name of the option to validate - * @value (allow-none): the value of the option to validate. + * @value: (allow-none): the value of the option to validate. * * Checks whether @name is a valid bond option and @value is a valid value for * the @name. If @value is %NULL, the function only validates the option name. @@ -840,6 +853,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) const char *arp_ip_target = NULL; const char *lacp_rate; const char *primary; + const char *s; NMBondMode bond_mode; guint i; const NMUtilsNamedValue *n; @@ -1067,6 +1081,32 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + s = _bond_get_option(self, NM_SETTING_BOND_OPTION_BALANCE_SLB); + if (s && _atoi(s) > 0) { + if (bond_mode != NM_BOND_MODE_XOR) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%s requires bond mode \"%s\""), + NM_SETTING_BOND_OPTION_BALANCE_SLB, + "balance-xor"); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + s = _bond_get_option(self, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY); + if (s + && _nm_setting_bond_xmit_hash_policy_from_string(s) + != NM_BOND_XMIT_HASH_POLICY_VLAN_SRCMAC) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%s requires xmit_hash_policy \"vlan+srcmac\""), + NM_SETTING_BOND_OPTION_BALANCE_SLB); + g_prefix_error(error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); + return FALSE; + } + } + if (!_nm_connection_verify_required_interface_name(connection, error)) return FALSE; @@ -1233,7 +1273,7 @@ nm_setting_bond_class_init(NMSettingBondClass *klass) setting_class->verify = verify; /** - * NMSettingBond:options: (type GHashTable(utf8,utf8)): + * NMSettingBond:options: (type GHashTable(utf8,utf8)) * * Dictionary of key/value pairs of bonding options. Both keys and values * must be strings. Option names must contain only alphanumeric characters @@ -1273,7 +1313,8 @@ nm_setting_bond_class_init(NMSettingBondClass *klass) */ _nm_properties_override_dbus(properties_override, "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); + &nm_sett_info_propert_type_deprecated_interface_name, + .dbus_deprecated = TRUE, ); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-bridge.c b/src/libnm-core-impl/nm-setting-bridge.c index 89611147..c1a2621d 100644 --- a/src/libnm-core-impl/nm-setting-bridge.c +++ b/src/libnm-core-impl/nm-setting-bridge.c @@ -109,7 +109,7 @@ G_DEFINE_TYPE(NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING) G_DEFINE_BOXED_TYPE(NMBridgeVlan, nm_bridge_vlan, _nm_bridge_vlan_dup, nm_bridge_vlan_unref) struct _NMBridgeVlan { - guint refcount; + int refcount; guint16 vid_start; guint16 vid_end; bool untagged : 1; @@ -132,6 +132,8 @@ NM_IS_BRIDGE_VLAN(const NMBridgeVlan *self, gboolean also_sealed) * Setting @vid_end to 0 is equivalent to setting it to @vid_start * and creates a single-id VLAN. * + * Since 1.42, ref-counting of #NMBridgeVlan is thread-safe. + * * Returns: (transfer full): the new #NMBridgeVlan object. * * Since: 1.18 @@ -148,11 +150,12 @@ nm_bridge_vlan_new(guint16 vid_start, guint16 vid_end) g_return_val_if_fail(vid_end <= NM_BRIDGE_VLAN_VID_MAX, NULL); g_return_val_if_fail(vid_start <= vid_end, NULL); - vlan = g_slice_new0(NMBridgeVlan); - vlan->refcount = 1; - vlan->vid_start = vid_start; - vlan->vid_end = vid_end; - + vlan = g_slice_new(NMBridgeVlan); + *vlan = (NMBridgeVlan){ + .refcount = 1, + .vid_start = vid_start, + .vid_end = vid_end, + }; return vlan; } @@ -164,6 +167,8 @@ nm_bridge_vlan_new(guint16 vid_start, guint16 vid_end) * * Returns: the input argument @vlan object. * + * Since 1.42, ref-counting of #NMBridgeVlan is thread-safe. + * * Since: 1.18 **/ NMBridgeVlan * @@ -171,9 +176,9 @@ nm_bridge_vlan_ref(NMBridgeVlan *vlan) { g_return_val_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE), NULL); - nm_assert(vlan->refcount < G_MAXUINT); + nm_assert(vlan->refcount < G_MAXINT); - vlan->refcount++; + g_atomic_int_inc(&vlan->refcount); return vlan; } @@ -184,6 +189,8 @@ nm_bridge_vlan_ref(NMBridgeVlan *vlan) * Decreases the reference count of the object. If the reference count * reaches zero the object will be destroyed. * + * Since 1.42, ref-counting of #NMBridgeVlan is thread-safe. + * * Since: 1.18 **/ void @@ -191,7 +198,7 @@ nm_bridge_vlan_unref(NMBridgeVlan *vlan) { g_return_if_fail(NM_IS_BRIDGE_VLAN(vlan, TRUE)); - if (--vlan->refcount == 0) + if (g_atomic_int_dec_and_test(&vlan->refcount)) g_slice_free(NMBridgeVlan, vlan); } @@ -1426,10 +1433,9 @@ nm_setting_bridge_class_init(NMSettingBridgeClass *klass) * If this field is left unspecified, the "ethernet.cloned-mac-address" is * referred instead to generate the initial MAC address. Note that setting * "ethernet.cloned-mac-address" anyway overwrites the MAC address of - * the bridge later while activating the bridge. Hence, this property - * is deprecated. + * the bridge later while activating the bridge. * - * Deprecated: 1.12: Use the ethernet.cloned-mac-address property instead. + * Deprecated: 1.12: Use the #NMSettingWired:cloned-mac-address property instead. **/ /* ---keyfile--- * property: mac-address @@ -1439,7 +1445,8 @@ nm_setting_bridge_class_init(NMSettingBridgeClass *klass) * example: mac-address=00:22:68:12:79:A2 * mac-address=0;34;104;18;121;162; * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: mac-address * variable: BRIDGE_MACADDR(+) * description: MAC address of the bridge. Note that this requires a recent @@ -1454,7 +1461,8 @@ nm_setting_bridge_class_init(NMSettingBridgeClass *klass) NM_SETTING_PARAM_INFERRABLE, NMSettingBridge, _priv.mac_address, - .direct_set_string_mac_address_len = ETH_ALEN); + .direct_set_string_mac_address_len = ETH_ALEN, + .is_deprecated = TRUE, ); /** * NMSettingBridge:stp: @@ -1748,7 +1756,8 @@ nm_setting_bridge_class_init(NMSettingBridgeClass *klass) */ _nm_properties_override_dbus(properties_override, "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); + &nm_sett_info_propert_type_deprecated_interface_name, + .dbus_deprecated = TRUE, ); /** * NMSettingBridge:group-address: diff --git a/src/libnm-core-impl/nm-setting-cdma.c b/src/libnm-core-impl/nm-setting-cdma.c index 46f29f96..c32af6b7 100644 --- a/src/libnm-core-impl/nm-setting-cdma.c +++ b/src/libnm-core-impl/nm-setting-cdma.c @@ -174,12 +174,12 @@ verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) } static GPtrArray * -need_secrets(NMSetting *setting) +need_secrets(NMSetting *setting, gboolean check_rerequest) { NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE(setting); GPtrArray *secrets = NULL; - if (!nm_str_is_empty(priv->password)) + if (!check_rerequest && !nm_str_is_empty(priv->password)) return NULL; if (priv->username) { diff --git a/src/libnm-core-impl/nm-setting-connection.c b/src/libnm-core-impl/nm-setting-connection.c index bc14c767..0ec36a89 100644 --- a/src/libnm-core-impl/nm-setting-connection.c +++ b/src/libnm-core-impl/nm-setting-connection.c @@ -339,7 +339,7 @@ nm_setting_connection_get_permission(NMSettingConnection *setting, g_return_val_if_fail(idx < nm_g_array_len(priv->permissions), FALSE); - permission = &g_array_index(priv->permissions, Permission, idx); + permission = &nm_g_array_index(priv->permissions, Permission, idx); switch (permission->ptype) { case PERM_TYPE_USER: NM_SET_OUT(out_ptype, NM_SETTINGS_CONNECTION_PERMISSION_USER); @@ -384,7 +384,7 @@ nm_setting_connection_permissions_user_allowed(NMSettingConnection *setting, con } for (i = 0; i < priv->permissions->len; i++) { - const Permission *permission = &g_array_index(priv->permissions, Permission, i); + const Permission *permission = &nm_g_array_index(priv->permissions, Permission, i); if (permission->ptype == PERM_TYPE_USER && nm_streq(permission->item, uname)) return TRUE; @@ -440,7 +440,7 @@ nm_setting_connection_add_permission(NMSettingConnection *setting, } for (i = 0; i < priv->permissions->len; i++) { - const Permission *permission = &g_array_index(priv->permissions, Permission, i); + const Permission *permission = &nm_g_array_index(priv->permissions, Permission, i); if (permission->ptype == PERM_TYPE_USER && nm_streq(permission->item, pitem)) return TRUE; @@ -511,7 +511,7 @@ nm_setting_connection_remove_permission_by_value(NMSettingConnection *setting, priv = NM_SETTING_CONNECTION_GET_PRIVATE(setting); if (priv->permissions) { for (i = 0; i < priv->permissions->len; i++) { - const Permission *permission = &g_array_index(priv->permissions, Permission, i); + const Permission *permission = &nm_g_array_index(priv->permissions, Permission, i); if (permission->ptype == PERM_TYPE_USER && nm_streq(permission->item, pitem)) { g_array_remove_index(priv->permissions, i); @@ -1023,7 +1023,7 @@ nm_setting_connection_get_dns_over_tls(NMSettingConnection *setting) * * Returns: the #NMSettingConnection:mptcp-flags property of the setting. * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ NMMptcpFlags nm_setting_connection_get_mptcp_flags(NMSettingConnection *setting) @@ -1490,7 +1490,7 @@ after_interface_name: guint i; for (i = 0; i < priv->permissions->len; i++) { - const Permission *permissions = &g_array_index(priv->permissions, Permission, i); + const Permission *permissions = &nm_g_array_index(priv->permissions, Permission, i); if (permissions->ptype != PERM_TYPE_USER) { g_set_error_literal(error, @@ -1709,7 +1709,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) strv = g_new(char *, l + 1u); for (i = 0; i < l; i++) - strv[i] = _permission_to_string(&g_array_index(priv->permissions, Permission, i)); + strv[i] = _permission_to_string(&nm_g_array_index(priv->permissions, Permission, i)); strv[i] = NULL; g_value_take_boxed(value, strv); @@ -1848,6 +1848,18 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass) * be generated by nm_utils_uuid_generate() or * nm_uuid_generate_from_string_str(). **/ + /* ---nmcli--- + * property: uuid + * format: a valid RFC4122 universally unique identifier (UUID). + * description: The connection.uuid is the real identifier of a profile. + * It cannot change and it must be unique. It is therefore often best + * to refer to a profile by UUID, for example with `nmcli connection up uuid $UUID`. + * + * The UUID cannot be changed, except in offline mode. In that case, + * the special values "new", "generate" and "" are allowed to generate + * a new random UUID. + * ---end--- + */ /* ---ifcfg-rh--- * property: uuid * variable: UUID(+) diff --git a/src/libnm-core-impl/nm-setting-ethtool.c b/src/libnm-core-impl/nm-setting-ethtool.c index 1db6c335..d5199823 100644 --- a/src/libnm-core-impl/nm-setting-ethtool.c +++ b/src/libnm-core-impl/nm-setting-ethtool.c @@ -29,7 +29,7 @@ * * Checks whether @optname is a valid option name for an offload feature. * - * %Returns: %TRUE, if @optname is valid + * Returns: %TRUE, if @optname is valid * * Note that nm_ethtool_optname_is_feature() was first added to the libnm header files * in 1.14.0 but forgot to actually add to the library. This happened belatedly in 1.20.0 and @@ -49,7 +49,7 @@ nm_ethtool_optname_is_feature(const char *optname) * * Checks whether @optname is a valid option name for a coalesce setting. * - * %Returns: %TRUE, if @optname is valid + * Returns: %TRUE, if @optname is valid * * Since: 1.26 */ @@ -65,7 +65,7 @@ nm_ethtool_optname_is_coalesce(const char *optname) * * Checks whether @optname is a valid option name for a ring setting. * - * %Returns: %TRUE, if @optname is valid + * Returns: %TRUE, if @optname is valid * * Since: 1.26 */ @@ -81,7 +81,7 @@ nm_ethtool_optname_is_ring(const char *optname) * * Checks whether @optname is a valid option name for a pause setting. * - * %Returns: %TRUE, if @optname is valid + * Returns: %TRUE, if @optname is valid * * Since: 1.32 */ diff --git a/src/libnm-core-impl/nm-setting-gsm.c b/src/libnm-core-impl/nm-setting-gsm.c index 15460ccc..3fe5dfa1 100644 --- a/src/libnm-core-impl/nm-setting-gsm.c +++ b/src/libnm-core-impl/nm-setting-gsm.c @@ -460,12 +460,12 @@ verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) } static GPtrArray * -need_secrets(NMSetting *setting) +need_secrets(NMSetting *setting, gboolean check_rerequest) { NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE(setting); GPtrArray *secrets = NULL; - if (priv->password && *priv->password) + if (!check_rerequest && priv->password && *priv->password) return NULL; if (priv->username) { @@ -545,7 +545,8 @@ nm_setting_gsm_class_init(NMSettingGsmClass *klass) PROP_NUMBER, NM_SETTING_PARAM_NONE, NMSettingGsmPrivate, - number); + number, + .is_deprecated = TRUE, ); /** * NMSettingGsm:username: @@ -744,10 +745,12 @@ nm_setting_gsm_class_init(NMSettingGsmClass *klass) /* Ignore incoming deprecated properties */ _nm_properties_override_dbus(properties_override, "allowed-bands", - &nm_sett_info_propert_type_deprecated_ignore_u); + &nm_sett_info_propert_type_deprecated_ignore_u, + .dbus_deprecated = TRUE, ); _nm_properties_override_dbus(properties_override, "network-type", - &nm_sett_info_propert_type_deprecated_ignore_i); + &nm_sett_info_propert_type_deprecated_ignore_i, + .dbus_deprecated = TRUE, ); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-hostname.c b/src/libnm-core-impl/nm-setting-hostname.c index 8a5e50be..399f41a8 100644 --- a/src/libnm-core-impl/nm-setting-hostname.c +++ b/src/libnm-core-impl/nm-setting-hostname.c @@ -134,7 +134,7 @@ nm_setting_hostname_init(NMSettingHostname *setting) * * Returns: (transfer full): the new empty #NMSettingHostname object * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ NMSetting * nm_setting_hostname_new(void) @@ -233,7 +233,7 @@ nm_setting_hostname_class_init(NMSettingHostnameClass *klass) * Since: 1.30 **/ /* ---ifcfg-rh--- - * property: from-dhcp + * property: from-dns-lookup * variable: HOSTNAME_FROM_DNS_LOOKUP(+) * default: missing variable means global default or 1 * description: whether the system hostname can be determined from reverse diff --git a/src/libnm-core-impl/nm-setting-infiniband.c b/src/libnm-core-impl/nm-setting-infiniband.c index 787b838b..410f1f06 100644 --- a/src/libnm-core-impl/nm-setting-infiniband.c +++ b/src/libnm-core-impl/nm-setting-infiniband.c @@ -378,7 +378,8 @@ nm_setting_infiniband_class_init(NMSettingInfinibandClass *klass) * or semicolon separated list of 20 decimal bytes (obsolete) * example: mac-address= 80:00:00:6d:fe:80:00:00:00:00:00:00:00:02:55:00:70:33:cf:01 * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: mac-address * variable: HWADDR * description: IBoIP 20-byte hardware address of the device (in traditional diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 73f98ab1..3a31848e 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -67,7 +67,7 @@ canonicalize_ip_binary(int family, const NMIPAddr *ip, gboolean null_any) if (null_any && nm_ip_addr_is_null(family, ip)) return NULL; - return nm_utils_inet_ntop_dup(family, ip); + return nm_inet_ntop_dup(family, ip); } static gboolean @@ -80,7 +80,7 @@ valid_ip(int family, const char *ip, NMIPAddr *addr, GError **error) family == AF_INET ? _("Missing IPv4 address") : _("Missing IPv6 address")); return FALSE; } - if (!nm_utils_parse_inaddr_bin(family, ip, NULL, addr)) { + if (!nm_inet_parse_bin(family, ip, NULL, addr)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, @@ -210,7 +210,7 @@ nm_ip_address_new_binary(int family, gconstpointer addr, guint prefix, GError ** *address = (NMIPAddress){ .refcount = 1, .family = family, - .address = nm_utils_inet_ntop_dup(family, addr), + .address = nm_inet_ntop_dup(family, addr), .prefix = prefix, }; @@ -420,7 +420,7 @@ nm_ip_address_set_address(NMIPAddress *address, const char *addr) if (!valid_ip(address->family, addr, &addr_bin, NULL)) { g_return_if_fail(addr != NULL); - g_return_if_fail(nm_utils_ipaddr_is_valid(address->family, addr)); + g_return_if_fail(nm_inet_is_valid(address->family, addr)); nm_assert_not_reached(); } @@ -462,7 +462,7 @@ nm_ip_address_set_address_binary(NMIPAddress *address, gconstpointer addr) g_return_if_fail(addr != NULL); g_free(address->address); - address->address = nm_utils_inet_ntop_dup(address->family, addr); + address->address = nm_inet_ntop_dup(address->family, addr); } /** @@ -885,7 +885,7 @@ nm_ip_route_get_dest(NMIPRoute *route) * Sets the destination property of this route object. * * @dest must be a valid address of @route's family. If you aren't sure you - * have a valid address, use nm_utils_ipaddr_is_valid() to check it. + * have a valid address, use nm_inet_is_valid() to check it. **/ void nm_ip_route_set_dest(NMIPRoute *route, const char *dest) @@ -895,7 +895,7 @@ nm_ip_route_set_dest(NMIPRoute *route, const char *dest) g_return_if_fail(route != NULL); if (!valid_ip(route->family, dest, &dest_bin, NULL)) { - g_return_if_fail(nm_utils_ipaddr_is_valid(route->family, dest)); + g_return_if_fail(nm_inet_is_valid(route->family, dest)); nm_assert_not_reached(); } @@ -937,7 +937,7 @@ nm_ip_route_set_dest_binary(NMIPRoute *route, gconstpointer dest) g_return_if_fail(dest != NULL); g_free(route->dest); - route->dest = nm_utils_inet_ntop_dup(route->family, dest); + route->dest = nm_inet_ntop_dup(route->family, dest); } /** @@ -1010,7 +1010,7 @@ nm_ip_route_set_next_hop(NMIPRoute *route, const char *next_hop) g_return_if_fail(route != NULL); if (next_hop && !valid_ip(route->family, next_hop, &next_hop_bin, NULL)) { - g_return_if_fail(!next_hop || nm_utils_ipaddr_is_valid(route->family, next_hop)); + g_return_if_fail(!next_hop || nm_inet_is_valid(route->family, next_hop)); nm_assert_not_reached(); } @@ -1278,6 +1278,10 @@ static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = { .v4 = TRUE, .v6 = TRUE, .type_detail = 'T', ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_WEIGHT, + G_VARIANT_TYPE_UINT32, + .v4 = TRUE, + .type_detail = 'w'), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE(NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, @@ -1299,8 +1303,9 @@ nm_ip_route_get_variant_attribute_spec(void) } typedef struct { - int type; - int scope; + int type; + int scope; + gint16 weight; } IPRouteAttrParseData; static gboolean @@ -1313,6 +1318,7 @@ _ip_route_attribute_validate(const char *name, { const NMVariantAttributeSpec *spec; const char *string; + guint32 u32; nm_assert(name); nm_assert(value); @@ -1354,7 +1360,7 @@ _ip_route_attribute_validate(const char *name, switch (spec->type_detail) { case 'a': /* IP address */ string = g_variant_get_string(value, NULL); - if (!nm_utils_ipaddr_is_valid(family, string)) { + if (!nm_inet_is_valid(family, string)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, @@ -1386,7 +1392,7 @@ _ip_route_attribute_validate(const char *name, return FALSE; } } - if (!nm_utils_ipaddr_is_valid(family, addr)) { + if (!nm_inet_is_valid(family, addr)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, @@ -1426,6 +1432,18 @@ _ip_route_attribute_validate(const char *name, if (parse_data) parse_data->scope = g_variant_get_byte(value); break; + case 'w': /* weight */ + u32 = g_variant_get_uint32(value); + if (u32 > 256) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("route weight cannot be larger than 256")); + return FALSE; + } + if (parse_data) + parse_data->weight = (guint16) u32; + break; case '\0': break; default: @@ -1475,8 +1493,9 @@ _nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error) guint attrs_len; guint i; IPRouteAttrParseData parse_data = { - .type = RTN_UNICAST, - .scope = -1, + .type = RTN_UNICAST, + .scope = -1, + .weight = 0, }; g_return_val_if_fail(route, FALSE); @@ -1525,6 +1544,17 @@ _nm_ip_route_attribute_validate_all(const NMIPRoute *route, GError **error) break; } + if (parse_data.weight > 0) { + if (parse_data.type != RTN_UNICAST) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("a %s route cannot have a ECMP multi-hop \"weight\""), + nm_net_aux_rtnl_rtntype_n2a(parse_data.type)); + return FALSE; + } + } + return TRUE; } @@ -1537,7 +1567,7 @@ struct NMIPRoutingRule { char *to_str; char *iifname; char *oifname; - guint ref_count; + int ref_count; guint32 priority; guint32 table; gint32 suppress_prefixlength; @@ -1636,9 +1666,11 @@ nm_ip_routing_rule_new(int addr_family) * nm_ip_routing_rule_new_clone: * @rule: the #NMIPRoutingRule to clone. * + * Since 1.42, ref-counting of #NMIPRoutingRule is thread-safe. + * * Returns: (transfer full): a newly created rule instance with * the same settings as @rule. Note that the instance will - * always be unsealred. + * always be unsealed. * * Since: 1.18 */ @@ -1704,11 +1736,12 @@ nm_ip_routing_rule_new_clone(const NMIPRoutingRule *rule) * @self: (allow-none): the #NMIPRoutingRule instance * * Increases the reference count of the instance. - * This is not thread-safe. * * Returns: (transfer full): the @self argument with incremented * reference count. * + * Since 1.42, ref-counting of #NMIPRoutingRule is thread-safe. + * * Since: 1.18 */ NMIPRoutingRule * @@ -1719,8 +1752,9 @@ nm_ip_routing_rule_ref(NMIPRoutingRule *self) g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); - nm_assert(self->ref_count < G_MAXUINT); - self->ref_count++; + nm_assert(self->ref_count < G_MAXINT); + + g_atomic_int_inc(&self->ref_count); return self; } @@ -1730,7 +1764,8 @@ nm_ip_routing_rule_ref(NMIPRoutingRule *self) * * Decreases the reference count of the instance and destroys * the instance if the reference count reaches zero. - * This is not thread-safe. + * + * Since 1.42, ref-counting of #NMIPRoutingRule is thread-safe. * * Since: 1.18 */ @@ -1742,7 +1777,7 @@ nm_ip_routing_rule_unref(NMIPRoutingRule *self) g_return_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE)); - if (--self->ref_count > 0) + if (!g_atomic_int_dec_and_test(&self->ref_count)) return; g_free(self->from_str); @@ -1913,7 +1948,7 @@ nm_ip_routing_rule_get_from(const NMIPRoutingRule *self) if (!self->from_str) { nm_assert(self->from_valid); ((NMIPRoutingRule *) self)->from_str = - nm_utils_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->from_bin); + nm_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->from_bin); } return self->from_str; } @@ -1970,12 +2005,10 @@ nm_ip_routing_rule_set_from(NMIPRoutingRule *self, const char *from, guint8 len) } nm_clear_g_free(&self->from_str); - self->from_has = TRUE; - self->from_len = len; - self->from_valid = nm_utils_parse_inaddr_bin(_ip_routing_rule_get_addr_family(self), - from, - NULL, - &self->from_bin); + self->from_has = TRUE; + self->from_len = len; + self->from_valid = + nm_inet_parse_bin(_ip_routing_rule_get_addr_family(self), from, NULL, &self->from_bin); if (!self->from_valid) self->from_str = g_strdup(from); } @@ -2015,7 +2048,7 @@ nm_ip_routing_rule_get_to(const NMIPRoutingRule *self) if (!self->to_str) { nm_assert(self->to_valid); ((NMIPRoutingRule *) self)->to_str = - nm_utils_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->to_bin); + nm_inet_ntop_dup(_ip_routing_rule_get_addr_family(self), &self->to_bin); } return self->to_str; } @@ -2076,7 +2109,7 @@ nm_ip_routing_rule_set_to(NMIPRoutingRule *self, const char *to, guint8 len) self->to_has = TRUE; self->to_len = len; self->to_valid = - nm_utils_parse_inaddr_bin(_ip_routing_rule_get_addr_family(self), to, NULL, &self->to_bin); + nm_inet_parse_bin(_ip_routing_rule_get_addr_family(self), to, NULL, &self->to_bin); if (!self->to_valid) self->to_str = g_strdup(to); } @@ -2938,12 +2971,12 @@ _rr_dbus_attr_from_name(const char *name) } } - idx = nm_utils_array_find_binary_search(rr_dbus_data, - sizeof(rr_dbus_data[0]), - _RR_DBUS_ATTR_NUM, - &name, - nm_strcmp_p_with_data, - NULL); + idx = nm_array_find_bsearch(rr_dbus_data, + _RR_DBUS_ATTR_NUM, + sizeof(rr_dbus_data[0]), + &name, + nm_strcmp_p_with_data, + NULL); if (idx < 0) return _RR_DBUS_ATTR_NUM; return idx; @@ -3169,7 +3202,7 @@ GVariant * nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self) { GVariantBuilder builder; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + char addr_str[NM_INET_ADDRSTRLEN]; g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); @@ -3222,9 +3255,9 @@ nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self) &builder, RR_DBUS_ATTR_FROM, g_variant_new_string(self->from_str - ?: nm_utils_inet_ntop(_ip_routing_rule_get_addr_family(self), - &self->from_bin, - addr_str))); + ?: nm_inet_ntop(_ip_routing_rule_get_addr_family(self), + &self->from_bin, + addr_str))); _rr_to_dbus_add(&builder, RR_DBUS_ATTR_FROM_LEN, g_variant_new_byte(self->from_len)); } @@ -3233,9 +3266,9 @@ nm_ip_routing_rule_to_dbus(const NMIPRoutingRule *self) &builder, RR_DBUS_ATTR_TO, g_variant_new_string(self->to_str - ?: nm_utils_inet_ntop(_ip_routing_rule_get_addr_family(self), - &self->to_bin, - addr_str))); + ?: nm_inet_ntop(_ip_routing_rule_get_addr_family(self), + &self->to_bin, + addr_str))); _rr_to_dbus_add(&builder, RR_DBUS_ATTR_TO_LEN, g_variant_new_byte(self->to_len)); } @@ -3634,11 +3667,11 @@ next_words_consumed: } if (!NM_IN_STRSET(word_from, NULL, "all")) { - if (!nm_utils_parse_inaddr_prefix_bin(addr_family, - word_from, - &addr_family, - &val_from, - &val_from_len)) { + if (!nm_inet_parse_with_prefix_bin(addr_family, + word_from, + &addr_family, + &val_from, + &val_from_len)) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, @@ -3650,11 +3683,11 @@ next_words_consumed: } if (!NM_IN_STRSET(word_to, NULL, "all")) { - if (!nm_utils_parse_inaddr_prefix_bin(addr_family, - word_to, - &addr_family, - &val_to, - &val_to_len)) { + if (!nm_inet_parse_with_prefix_bin(addr_family, + word_to, + &addr_family, + &val_to, + &val_to_len)) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED, @@ -3753,7 +3786,7 @@ _rr_string_append_inet_addr(NMStrBuf *str, const NMIPAddr *addr_bin, guint8 addr_len) { - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + char addr_str[NM_INET_ADDRSTRLEN]; if (addr_len == 0) { if (required) { @@ -3768,7 +3801,7 @@ _rr_string_append_inet_addr(NMStrBuf *str, nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(str, ' '), "%s %s", is_from ? "from" : "to", - nm_utils_inet_ntop(addr_family, addr_bin, addr_str)); + nm_inet_ntop(addr_family, addr_bin, addr_str)); if (addr_len != nm_utils_addr_family_to_size(addr_family) * 8) { nm_str_buf_append_printf(str, "/%u", addr_len); } @@ -3793,8 +3826,8 @@ nm_ip_routing_rule_to_string(const NMIPRoutingRule *self, GHashTable *extra_args, GError **error) { - int addr_family; - NMStrBuf str; + int addr_family; + nm_auto_str_buf NMStrBuf str = NM_STR_BUF_INIT_A(NM_UTILS_GET_NEXT_REALLOC_SIZE_488, FALSE); g_return_val_if_fail(NM_IS_IP_ROUTING_RULE(self, TRUE), NULL); @@ -3832,8 +3865,6 @@ nm_ip_routing_rule_to_string(const NMIPRoutingRule *self, } } - str = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_32, FALSE); - if (self->priority_has) { nm_str_buf_append_printf(nm_str_buf_append_required_delimiter(&str, ' '), "priority %u", @@ -3940,7 +3971,7 @@ nm_ip_routing_rule_to_string(const NMIPRoutingRule *self, nm_net_aux_rtnl_rtntype_n2a_maybe_buf(self->action, sbuf)); } - return nm_str_buf_finalize(&str, NULL); + return nm_str_buf_dup_str(&str); } /*****************************************************************************/ @@ -3967,7 +3998,8 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMSettingIPConfig, PROP_DHCP_TIMEOUT, PROP_REQUIRED_TIMEOUT, PROP_DHCP_IAID, - PROP_DHCP_REJECT_SERVERS, ); + PROP_DHCP_REJECT_SERVERS, + PROP_AUTO_ROUTE_EXT_GW, ); G_DEFINE_ABSTRACT_TYPE(NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING) @@ -3991,9 +4023,6 @@ _NM_SETTING_IP_CONFIG_GET_PRIVATE(NMSettingIPConfig *self) /*****************************************************************************/ -#define NM_SETTING_IP_CONFIG_GET_FAMILY(setting) \ - (NM_IS_SETTING_IP4_CONFIG(setting) ? AF_INET : AF_INET6) - /** * nm_setting_ip_config_get_method: * @setting: the #NMSettingIPConfig @@ -4021,7 +4050,7 @@ nm_setting_ip_config_get_num_dns(NMSettingIPConfig *setting) { g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), 0); - return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns->len; + return nm_g_ptr_array_len(NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->dns); } /** @@ -4039,11 +4068,35 @@ nm_setting_ip_config_get_dns(NMSettingIPConfig *setting, int idx) g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NULL); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_val_if_fail(idx >= 0 && idx < priv->dns->len, NULL); + g_return_val_if_fail(idx >= 0 && ((guint) idx) < nm_g_ptr_array_len(priv->dns), NULL); return priv->dns->pdata[idx]; } +static gboolean +_ip_config_add_dns(NMSettingIPConfig *setting, const char *dns) +{ + NMSettingIPConfigPrivate *priv; + gs_free char *s_free = NULL; + const char *s; + + nm_assert(NM_IS_SETTING_IP_CONFIG(setting)); + nm_assert(dns); + + priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); + + s = nm_utils_dnsname_normalize(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), dns, &s_free); + if (!s) + s = dns; + + if (nm_strv_ptrarray_contains(priv->dns, s)) + return FALSE; + + nm_strv_ptrarray_add_string_take(nm_strv_ptrarray_ensure(&priv->dns), + g_steal_pointer(&s_free) ?: g_strdup(s)); + return TRUE; +} + /** * nm_setting_ip_config_add_dns: * @setting: the #NMSettingIPConfig @@ -4053,36 +4106,20 @@ nm_setting_ip_config_get_dns(NMSettingIPConfig *setting, int idx) * * Returns: %TRUE if the DNS server was added; %FALSE if the server was already * known + * + * Before 1.42, setting @dns to an invalid string was treated as user-error. + * Now, also invalid DNS values can be set, but will be rejected later during + * nm_connection_verify(). **/ gboolean nm_setting_ip_config_add_dns(NMSettingIPConfig *setting, const char *dns) { - NMSettingIPConfigPrivate *priv; - int addr_family; - NMIPAddr dns_bin; - char dns_canonical[NM_UTILS_INET_ADDRSTRLEN]; - guint i; - g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); + g_return_val_if_fail(dns, FALSE); - addr_family = NM_SETTING_IP_CONFIG_GET_FAMILY(setting); - - if (!valid_ip(addr_family, dns, &dns_bin, NULL)) { - g_return_val_if_fail(dns != NULL, FALSE); - g_return_val_if_fail(nm_utils_ipaddr_is_valid(addr_family, dns), FALSE); - nm_assert_not_reached(); - } - - priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - - nm_utils_inet_ntop(addr_family, &dns_bin, dns_canonical); - - for (i = 0; i < priv->dns->len; i++) { - if (nm_streq(dns_canonical, priv->dns->pdata[i])) - return FALSE; - } + if (!_ip_config_add_dns(setting, dns)) + return FALSE; - g_ptr_array_add(priv->dns, g_strdup(dns_canonical)); _notify(setting, PROP_DNS); return TRUE; } @@ -4102,7 +4139,8 @@ nm_setting_ip_config_remove_dns(NMSettingIPConfig *setting, int idx) g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - g_return_if_fail(idx >= 0 && idx < priv->dns->len); + + g_return_if_fail(idx >= 0 && ((guint) idx) < nm_g_ptr_array_len(priv->dns)); g_ptr_array_remove_index(priv->dns, idx); _notify(setting, PROP_DNS); @@ -4116,38 +4154,39 @@ nm_setting_ip_config_remove_dns(NMSettingIPConfig *setting, int idx) * Removes the DNS server @dns. * * Returns: %TRUE if the DNS server was found and removed; %FALSE if it was not. + * + * Before 1.42, setting @dns to an invalid string was treated as user-error. **/ gboolean nm_setting_ip_config_remove_dns_by_value(NMSettingIPConfig *setting, const char *dns) { NMSettingIPConfigPrivate *priv; - int addr_family; - NMIPAddr dns_bin; - char dns_canonical[NM_UTILS_INET_ADDRSTRLEN]; - guint i; + gssize idx; g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); - - addr_family = NM_SETTING_IP_CONFIG_GET_FAMILY(setting); - - if (!valid_ip(addr_family, dns, &dns_bin, NULL)) { - g_return_val_if_fail(dns != NULL, FALSE); - g_return_val_if_fail(nm_utils_ipaddr_is_valid(addr_family, dns), FALSE); - nm_assert_not_reached(); - } + g_return_val_if_fail(dns, FALSE); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - nm_utils_inet_ntop(addr_family, &dns_bin, dns_canonical); + /* "priv->dns" can only contain normalized or invalid values. Expect that + * "dns" is normalized already, so lookup first for that string. Only + * if that fails, fallback to normalize "dns". */ + idx = nm_strv_ptrarray_find_first(priv->dns, dns); + if (idx < 0) { + gs_free char *s_free = NULL; + const char *s; - for (i = 0; i < priv->dns->len; i++) { - if (nm_streq(dns_canonical, priv->dns->pdata[i])) { - g_ptr_array_remove_index(priv->dns, i); - _notify(setting, PROP_DNS); - return TRUE; - } + s = nm_utils_dnsname_normalize(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), dns, &s_free); + if (s && !nm_streq(dns, s)) + idx = nm_strv_ptrarray_find_first(priv->dns, dns); } - return FALSE; + + if (idx < 0) + return FALSE; + + g_ptr_array_remove_index(priv->dns, idx); + _notify(setting, PROP_DNS); + return TRUE; } /** @@ -4165,7 +4204,7 @@ nm_setting_ip_config_clear_dns(NMSettingIPConfig *setting) priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); - if (priv->dns->len != 0) { + if (nm_g_ptr_array_len(priv->dns) != 0) { g_ptr_array_set_size(priv->dns, 0); _notify(setting, PROP_DNS); } @@ -4610,7 +4649,7 @@ nm_setting_ip_config_add_address(NMSettingIPConfig *setting, NMIPAddress *addres g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); g_return_val_if_fail(address != NULL, FALSE); - g_return_val_if_fail(address->family == NM_SETTING_IP_CONFIG_GET_FAMILY(setting), FALSE); + g_return_val_if_fail(address->family == NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), FALSE); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); for (i = 0; i < priv->addresses->len; i++) { @@ -4767,7 +4806,7 @@ nm_setting_ip_config_add_route(NMSettingIPConfig *setting, NMIPRoute *route) g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), FALSE); g_return_val_if_fail(route != NULL, FALSE); - g_return_val_if_fail(route->family == NM_SETTING_IP_CONFIG_GET_FAMILY(setting), FALSE); + g_return_val_if_fail(route->family == NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), FALSE); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); for (i = 0; i < priv->routes->len; i++) { @@ -4963,7 +5002,7 @@ nm_setting_ip_config_add_routing_rule(NMSettingIPConfig *setting, NMIPRoutingRul g_return_if_fail(NM_IS_SETTING_IP_CONFIG(setting)); g_return_if_fail(NM_IS_IP_ROUTING_RULE(routing_rule, TRUE)); g_return_if_fail(_ip_routing_rule_get_addr_family(routing_rule) - == NM_SETTING_IP_CONFIG_GET_FAMILY(setting)); + == NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(setting); @@ -5021,7 +5060,7 @@ nm_setting_ip_config_clear_routing_rules(NMSettingIPConfig *setting) } static GVariant * -_routing_rules_dbus_only_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +routing_rules_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { NMSettingIPConfig *self = NM_SETTING_IP_CONFIG(setting); NMSettingIPConfigPrivate *priv; @@ -5052,7 +5091,7 @@ _routing_rules_dbus_only_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -_routing_rules_dbus_only_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +routing_rules_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { GVariantIter iter_rules; GVariant *rule_var; @@ -5295,7 +5334,7 @@ nm_setting_ip_config_get_required_timeout(NMSettingIPConfig *setting) * * Returns: the configured DHCP IAID (Identity Association Identifier) * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ const char * nm_setting_ip_config_get_dhcp_iaid(NMSettingIPConfig *setting) @@ -5390,6 +5429,22 @@ nm_setting_ip_config_clear_dhcp_reject_servers(NMSettingIPConfig *setting) } } +/** + * nm_setting_ip_config_get_auto_route_ext_gw: + * @setting: the #NMSettingIPConfig + * + * Returns: the #NMSettingIPConfig:auto-route-ext-gw property of the setting + * + * Since: 1.42 + **/ +NMTernary +nm_setting_ip_config_get_auto_route_ext_gw(NMSettingIPConfig *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_CONFIG(setting), NM_TERNARY_DEFAULT); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE(setting)->auto_route_ext_gw; +} + static gboolean verify_label(const char *label) { @@ -5442,20 +5497,26 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } /* Validate DNS */ - for (i = 0; i < priv->dns->len; i++) { - const char *dns = priv->dns->pdata[i]; - - if (!nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), dns)) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("%d. DNS server address is invalid"), - (int) (i + 1)); - g_prefix_error(error, - "%s.%s: ", - nm_setting_get_name(setting), - NM_SETTING_IP_CONFIG_DNS); - return FALSE; + if (priv->dns) { + for (i = 0; i < priv->dns->len; i++) { + const char *dns = priv->dns->pdata[i]; + + if (!nm_utils_dnsname_parse(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), + dns, + NULL, + NULL, + NULL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%u. DNS server address is invalid"), + (i + 1u)); + g_prefix_error(error, + "%s.%s: ", + nm_setting_get_name(setting), + NM_SETTING_IP_CONFIG_DNS); + return FALSE; + } } } @@ -5464,7 +5525,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) NMIPAddress *addr = (NMIPAddress *) priv->addresses->pdata[i]; GVariant *label; - if (nm_ip_address_get_family(addr) != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { + if (nm_ip_address_get_family(addr) != NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -5521,7 +5582,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (!nm_utils_ipaddr_is_valid(NM_SETTING_IP_CONFIG_GET_FAMILY(setting), priv->gateway)) { + if (!nm_inet_is_valid(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), priv->gateway)) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -5539,7 +5600,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) gs_free_error GError *local = NULL; NMIPRoute *route = (NMIPRoute *) priv->routes->pdata[i]; - if (nm_ip_route_get_family(route) != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { + if (nm_ip_route_get_family(route) != NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -5572,7 +5633,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) gs_free_error GError *local = NULL; if (_ip_routing_rule_get_addr_family(rule) - != NM_SETTING_IP_CONFIG_GET_FAMILY(setting)) { + != NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -5629,7 +5690,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) if (priv->dhcp_hostname_flags != (NMDhcpHostnameFlags) priv->dhcp_hostname_flags || !_nm_utils_validate_dhcp_hostname_flags(priv->dhcp_hostname_flags, - NM_SETTING_IP_CONFIG_GET_FAMILY(setting), + NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), error)) { g_prefix_error(error, "%s.%s: ", @@ -5640,7 +5701,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) /* Validate reject servers */ if (priv->dhcp_reject_servers && priv->dhcp_reject_servers->len != 0) { - if (NM_SETTING_IP_CONFIG_GET_FAMILY(setting) != AF_INET) { + if (NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting) != AF_INET) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -5653,16 +5714,16 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } for (i = 0; i < priv->dhcp_reject_servers->len; i++) { - if (!nm_utils_parse_inaddr_prefix( - NM_SETTING_IP_CONFIG_GET_FAMILY(setting), - g_array_index(priv->dhcp_reject_servers, const char *, i), + if (!nm_inet_parse_with_prefix_str( + NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), + nm_g_array_index(priv->dhcp_reject_servers, const char *, i), NULL, NULL)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid IP or subnet"), - g_array_index(priv->dhcp_reject_servers, const char *, i)); + nm_g_array_index(priv->dhcp_reject_servers, const char *, i)); g_prefix_error(error, "%s.%s: ", nm_setting_get_name(setting), @@ -5736,6 +5797,20 @@ _nm_setting_ip_config_compare_fcn_routes(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm return TRUE; } +NMTernary +_nm_setting_ip_config_compare_fcn_dns(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil) +{ + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) + return NM_TERNARY_DEFAULT; + + if (!set_b) + return TRUE; + + return (nm_strv_ptrarray_cmp(NM_SETTING_IP_CONFIG_GET_PRIVATE(set_a)->dns, + NM_SETTING_IP_CONFIG_GET_PRIVATE(set_b)->dns) + == 0); +} + static NMTernary compare_fcn_routing_rules(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil) { @@ -5838,6 +5913,35 @@ _nm_setting_property_from_dbus_fcn_direct_ip_config_gateway( error); } +static GVariant * +dns_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +{ + GPtrArray *arr; + + if (!_nm_connection_serialize_non_secret(flags)) + return NULL; + + arr = _nm_setting_ip_config_get_dns_array(NM_SETTING_IP_CONFIG(setting)); + if (nm_g_ptr_array_len(arr) == 0) + return NULL; + return g_variant_new_strv((const char *const *) arr->pdata, arr->len); +} + +static gboolean +dns_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +{ + gs_free const char **strv = NULL; + + if (_nm_setting_use_legacy_property(setting, connection_dict, "dns", "dns-data")) { + *out_is_modified = FALSE; + return TRUE; + } + + strv = g_variant_get_strv(value, NULL); + g_object_set(setting, NM_SETTING_IP_CONFIG_DNS, strv, NULL); + return TRUE; +} + GArray * _nm_sett_info_property_override_create_array_ip_config(int addr_family) { @@ -5880,16 +5984,21 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family) /* ---dbus--- * property: routing-rules * format: array of 'a{sv}' - * description: Array of dictionaries for routing rules. + * description: Array of dictionaries for routing rules. Each routing rule + * supports the following options: action (y), dport-end (q), + * dport-start (q), family (i), from (s), from-len (y), fwmark (u), + * fwmask (u), iifname (s), invert (b), ipproto (s), oifname (s), + * priority (u), sport-end (q), sport-start (q), supress-prefixlength (i), + * table (u), to (s), tos (y), to-len (y), range-end (u), range-start (u). * ---end--- */ _nm_properties_override_dbus( properties_override, NM_SETTING_IP_CONFIG_ROUTING_RULES, NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = _routing_rules_dbus_only_synth, + .to_dbus_fcn = routing_rules_to_dbus, .compare_fcn = compare_fcn_routing_rules, - .from_dbus_fcn = _routing_rules_dbus_only_set, )); + .from_dbus_fcn = routing_rules_from_dbus, )); _nm_properties_override_gobj( properties_override, @@ -5919,6 +6028,21 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family) .direct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE(bool, NMSettingIPConfigPrivate, ignore_auto_dns)); + /* ---dbus--- + * property: dns-data + * format: array of strings + * description: Array of DNS name servers. This replaces the deprecated + * "dns" property. Each name server can also contain a DoT server name. + * ---end--- + */ + _nm_properties_override_dbus( + properties_override, + "dns-data", + NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("as"), + .to_dbus_fcn = dns_data_to_dbus, + .from_dbus_fcn = dns_data_from_dbus, + .compare_fcn = _nm_setting_property_compare_fcn_ignore, )); + _nm_properties_override_gobj( properties_override, obj_properties[PROP_DNS_PRIORITY], @@ -5974,6 +6098,13 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family) &nm_sett_info_propert_type_direct_boolean, .direct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE(bool, NMSettingIPConfigPrivate, may_fail)); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_AUTO_ROUTE_EXT_GW], + &nm_sett_info_propert_type_direct_enum, + .direct_offset = + NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, auto_route_ext_gw)); + return properties_override; } @@ -6028,9 +6159,17 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps switch (prop_id) { case PROP_DNS: - g_ptr_array_unref(priv->dns); - priv->dns = nm_strv_to_ptrarray(g_value_get_boxed(value)); + { + gs_unref_ptrarray GPtrArray *dns_old = NULL; + + dns_old = g_steal_pointer(&priv->dns); + strv = g_value_get_boxed(value); + if (strv) { + for (i = 0; strv[i]; i++) + _ip_config_add_dns(setting, strv[i]); + } break; + } case PROP_DNS_SEARCH: g_ptr_array_unref(priv->dns_search); priv->dns_search = nm_strv_to_ptrarray(g_value_get_boxed(value)); @@ -6082,7 +6221,6 @@ _nm_setting_ip_config_private_init(gpointer self, NMSettingIPConfigPrivate *priv { nm_assert(NM_IS_SETTING_IP_CONFIG(self)); - priv->dns = g_ptr_array_new_with_free_func(g_free); priv->dns_search = g_ptr_array_new_with_free_func(g_free); priv->addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); priv->routes = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_route_unref); @@ -6100,7 +6238,7 @@ finalize(GObject *object) NMSettingIPConfig *self = NM_SETTING_IP_CONFIG(object); NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE(self); - g_ptr_array_unref(priv->dns); + nm_g_ptr_array_unref(priv->dns); g_ptr_array_unref(priv->dns_search); nm_g_ptr_array_unref(priv->dns_options); g_ptr_array_unref(priv->addresses); @@ -6159,12 +6297,18 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) * NMSettingIPConfig:dns: * * Array of IP addresses of DNS servers. + * + * For DoT (DNS over TLS), the SNI server name can be specified by appending + * "#example.com" to the IP address of the DNS server. This currently only has + * effect when using systemd-resolved. **/ - obj_properties[PROP_DNS] = g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS, - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DNS] = + g_param_spec_boxed(NM_SETTING_IP_CONFIG_DNS, + "", + "", + G_TYPE_STRV, + /* On D-Bus, "dns" is deprecated for "dns-data". */ + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * NMSettingIPConfig:dns-search: @@ -6295,12 +6439,9 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) "", "", G_TYPE_PTR_ARRAY, - /* "addresses" is a legacy D-Bus property, because the - * "addresses" GObject property normally gets set from - * the "address-data" D-Bus property... - */ - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | NM_SETTING_PARAM_LEGACY - | G_PARAM_STATIC_STRINGS); + /* On D-Bus, "addresses" is deprecated for "address-data". */ + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | NM_SETTING_PARAM_UNUSED1 | G_PARAM_STATIC_STRINGS); /** * NMSettingIPConfig:gateway: @@ -6322,6 +6463,8 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) "", "", NULL, + /* On D-Bus, the legacy property "addresses" contains the gateway. + * This was replaced by "address-data" and "gateway". */ G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); /** @@ -6334,9 +6477,9 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) "", "", G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | - /* See :addresses above Re: LEGACY */ - NM_SETTING_PARAM_LEGACY | G_PARAM_STATIC_STRINGS); + /* On D-Bus, "routes" is deprecated for "route-data". */ + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | NM_SETTING_PARAM_UNUSED1 | G_PARAM_STATIC_STRINGS); /** * NMSettingIPConfig:route-metric: @@ -6635,5 +6778,24 @@ nm_setting_ip_config_class_init(NMSettingIPConfigClass *klass) G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + /** + * NMSettingIPConfig:auto-route-ext-gw: + * + * 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. + * + * Since: 1.42 + */ + obj_properties[PROP_AUTO_ROUTE_EXT_GW] = + g_param_spec_enum(NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, + "", + "", + NM_TYPE_TERNARY, + NM_TERNARY_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); } diff --git a/src/libnm-core-impl/nm-setting-ip-tunnel.c b/src/libnm-core-impl/nm-setting-ip-tunnel.c index 73416813..7fb8b017 100644 --- a/src/libnm-core-impl/nm-setting-ip-tunnel.c +++ b/src/libnm-core-impl/nm-setting-ip-tunnel.c @@ -28,6 +28,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT, PROP_OUTPUT_KEY, PROP_ENCAPSULATION_LIMIT, PROP_FLOW_LABEL, + PROP_FWMARK, PROP_MTU, PROP_FLAGS, ); @@ -41,6 +42,7 @@ typedef struct { guint32 tos; guint32 encapsulation_limit; guint32 flow_label; + guint32 fwmark; guint32 mode; guint32 mtu; guint32 flags; @@ -240,7 +242,7 @@ nm_setting_ip_tunnel_get_output_key(NMSettingIPTunnel *setting) * * Returns: the encapsulation limit value * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ guint nm_setting_ip_tunnel_get_encapsulation_limit(NMSettingIPTunnel *setting) @@ -258,7 +260,7 @@ nm_setting_ip_tunnel_get_encapsulation_limit(NMSettingIPTunnel *setting) * * Returns: the flow label value * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ guint nm_setting_ip_tunnel_get_flow_label(NMSettingIPTunnel *setting) @@ -269,6 +271,24 @@ nm_setting_ip_tunnel_get_flow_label(NMSettingIPTunnel *setting) } /** + * nm_setting_ip_tunnel_get_fwmark: + * @setting: the #NMSettingIPTunnel + * + * Returns the #NMSettingIPTunnel:fwmark property of the setting. + * + * Returns: the fwmark value + * + * Since: 1.42 + **/ +guint32 +nm_setting_ip_tunnel_get_fwmark(NMSettingIPTunnel *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_IP_TUNNEL(setting), 0); + + return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->fwmark; +} + +/** * nm_setting_ip_tunnel_get_mtu: * @setting: the #NMSettingIPTunnel * @@ -366,7 +386,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->local && !nm_utils_ipaddr_is_valid(family, priv->local)) { + if (priv->local && !nm_inet_is_valid(family, priv->local)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -392,7 +412,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (!nm_utils_ipaddr_is_valid(family, priv->remote)) { + if (!nm_inet_is_valid(family, priv->remote)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -411,11 +431,13 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) NM_IP_TUNNEL_MODE_GRE, NM_IP_TUNNEL_MODE_GRETAP, NM_IP_TUNNEL_MODE_IP6GRE, - NM_IP_TUNNEL_MODE_IP6GRETAP)) { + NM_IP_TUNNEL_MODE_IP6GRETAP, + NM_IP_TUNNEL_MODE_VTI, + NM_IP_TUNNEL_MODE_VTI6)) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("tunnel keys can only be specified for GRE tunnels")); + _("tunnel keys can only be specified for GRE and VTI tunnels")); return FALSE; } } @@ -484,6 +506,18 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if (priv->fwmark && !NM_IN_SET(priv->mode, NM_IP_TUNNEL_MODE_VTI, NM_IP_TUNNEL_MODE_VTI6)) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can be set only on VTI tunnels")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_FWMARK); + return FALSE; + } + if (nm_connection_get_setting_wired(connection) && !_nm_ip_tunnel_mode_is_layer2(priv->mode)) { g_set_error(error, NM_CONNECTION_ERROR, @@ -728,6 +762,25 @@ nm_setting_ip_tunnel_class_init(NMSettingIPTunnelClass *klass) flow_label); /** + * NMSettingIPTunnel:fwmark: + * + * The fwmark value to assign to tunnel packets. This property can be set + * to a non zero value only on VTI and VTI6 tunnels. + * + * Since: 1.42 + **/ + _nm_setting_property_define_direct_uint32(properties_override, + obj_properties, + NM_SETTING_IP_TUNNEL_FWMARK, + PROP_FWMARK, + 0, + G_MAXUINT32, + 0, + NM_SETTING_PARAM_INFERRABLE, + NMSettingIPTunnelPrivate, + fwmark); + + /** * NMSettingIPTunnel:mtu: * * If non-zero, only transmit packets of the specified size or smaller, diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index d991152c..f847918e 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -138,7 +138,7 @@ nm_setting_ip4_config_get_dhcp_vendor_class_identifier(NMSettingIP4Config *setti * * Returns: the link-local configuration * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ NMSettingIP4LinkLocal nm_setting_ip4_config_get_link_local(NMSettingIP4Config *setting) @@ -388,21 +388,29 @@ ip4_dns_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) GPtrArray *dns; dns = _nm_setting_ip_config_get_dns_array(NM_SETTING_IP_CONFIG(setting)); - if (nm_g_ptr_array_len(dns) == 0) return NULL; - return _nm_utils_ip4_dns_to_variant((const char *const *) dns->pdata, dns->len); + return nm_utils_dns_to_variant(AF_INET, (const char *const *) dns->pdata, dns->len); } -static void -ip4_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil) +static gboolean +ip4_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - g_value_take_boxed(to, nm_utils_ip4_dns_from_variant(from)); + gs_strfreev char **strv = NULL; + + if (!_nm_setting_use_legacy_property(setting, connection_dict, "dns", "dns-data")) { + *out_is_modified = FALSE; + return TRUE; + } + + strv = nm_utils_ip4_dns_from_variant(value); + g_object_set(setting, NM_SETTING_IP_CONFIG_DNS, strv, NULL); + return TRUE; } static GVariant * -ip4_addresses_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_addresses_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *addrs = NULL; const char *gateway; @@ -413,12 +421,13 @@ ip4_addresses_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip4_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip4_addresses_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *addrs; - GVariant *s_ip4; - char **labels, *gateway = NULL; - int i; + gs_unref_ptrarray GPtrArray *addrs = NULL; + gs_unref_variant GVariant *s_ip4 = NULL; + gs_free const char **labels = NULL; + gs_free char *gateway = NULL; + guint i; /* FIXME: properly handle errors */ @@ -432,15 +441,15 @@ ip4_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) s_ip4 = g_variant_lookup_value(connection_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); - if (g_variant_lookup(s_ip4, "address-labels", "^as", &labels)) { - for (i = 0; i < addrs->len && labels[i]; i++) - if (*labels[i]) + if (g_variant_lookup(s_ip4, "address-labels", "^a&s", &labels)) { + for (i = 0; i < addrs->len && labels[i]; i++) { + if (*labels[i]) { nm_ip_address_set_attribute(addrs->pdata[i], NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string(labels[i])); - g_strfreev(labels); + } + } } - g_variant_unref(s_ip4); g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, @@ -448,52 +457,50 @@ ip4_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); - g_ptr_array_unref(addrs); - g_free(gateway); return TRUE; } static GVariant * -ip4_address_labels_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_address_labels_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG(setting); gboolean have_labels = FALSE; - GPtrArray *labels; - GVariant *ret; - int num_addrs, i; + gs_free GVariant **labels_free = NULL; + GVariant *s_empty; + GVariant **labels; + guint num_addrs; + guint i; if (!_nm_connection_serialize_non_secret(flags)) return NULL; num_addrs = nm_setting_ip_config_get_num_addresses(s_ip); + if (num_addrs == 0) + return NULL; + + labels = nm_malloc_maybe_a(500, sizeof(gpointer) * num_addrs, &labels_free); + + s_empty = nm_g_variant_singleton_s_empty(); + for (i = 0; i < num_addrs; i++) { NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, i); GVariant *label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); if (label) { have_labels = TRUE; - break; - } + labels[i] = label; + } else + labels[i] = s_empty; } + if (!have_labels) return NULL; - labels = g_ptr_array_sized_new(num_addrs); - for (i = 0; i < num_addrs; i++) { - NMIPAddress *addr = nm_setting_ip_config_get_address(s_ip, i); - GVariant *label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL); - - g_ptr_array_add(labels, (char *) (label ? g_variant_get_string(label, NULL) : "")); - } - - ret = g_variant_new_strv((const char *const *) labels->pdata, labels->len); - g_ptr_array_unref(labels); - - return ret; + return g_variant_new_array(G_VARIANT_TYPE_STRING, labels, num_addrs); } static GVariant * -ip4_address_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_address_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *addrs = NULL; @@ -505,9 +512,9 @@ ip4_address_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip4_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip4_address_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *addrs; + gs_unref_ptrarray GPtrArray *addrs = NULL; /* FIXME: properly handle errors */ @@ -519,12 +526,11 @@ ip4_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) addrs = nm_utils_ip_addresses_from_variant(value, AF_INET); g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); - g_ptr_array_unref(addrs); return TRUE; } static GVariant * -ip4_routes_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_routes_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *routes = NULL; @@ -533,9 +539,9 @@ ip4_routes_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip4_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip4_routes_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *routes; + gs_unref_ptrarray GPtrArray *routes = NULL; /* FIXME: properly handle errors */ @@ -546,12 +552,11 @@ ip4_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) routes = nm_utils_ip4_routes_from_variant(value); g_object_set(setting, property_info->name, routes, NULL); - g_ptr_array_unref(routes); return TRUE; } static GVariant * -ip4_route_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip4_route_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *routes = NULL; @@ -563,9 +568,9 @@ ip4_route_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip4_route_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip4_route_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *routes; + gs_unref_ptrarray GPtrArray *routes = NULL; /* FIXME: properly handle errors */ @@ -577,7 +582,6 @@ ip4_route_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) routes = nm_utils_ip_routes_from_variant(value, AF_INET); g_object_set(setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); - g_ptr_array_unref(routes); return TRUE; } @@ -620,13 +624,15 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) setting_class->verify = verify; setting_ip_config_class->private_offset = g_type_class_get_instance_private_offset(klass); + setting_ip_config_class->is_ipv4 = TRUE; + setting_ip_config_class->addr_family = AF_INET; /* ---ifcfg-rh--- * property: method * variable: BOOTPROTO - * format: string - * values: none, dhcp (bootp), static, ibft, autoip, shared - * default: none + * format: string + * values: none, dhcp (bootp), static, ibft, autoip, shared + * default: none * description: Method used for IPv4 protocol configuration. * ---end--- */ @@ -637,10 +643,11 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * description: List of DNS servers. * example: dns=1.2.3.4;8.8.8.8;8.8.4.4; * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: dns * variable: DNS1, DNS2, ... - * format: string + * format: string * description: List of DNS servers. Even if NetworkManager supports many DNS * servers, initscripts and resolver only care about the first three, usually. * example: DNS1=1.2.3.4 DNS2=10.0.0.254 DNS3=8.8.8.8 @@ -650,7 +657,7 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) /* ---ifcfg-rh--- * property: dns-search * variable: DOMAIN - * format: string (space-separated domains) + * format: string (space-separated domains) * description: List of DNS search domains. * ---end--- */ @@ -662,7 +669,8 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * description: List of static IP addresses. * example: address1=192.168.100.100/24 address2=10.1.1.5/24 * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: addresses * variable: IPADDR, PREFIX (NETMASK), IPADDR1, PREFIX1 (NETMASK1), ... * description: List of static IP addresses. @@ -677,7 +685,8 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * description: Gateway IP addresses as a string. * example: gateway=192.168.100.1 * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: gateway * variable: GATEWAY * description: Gateway IP address. @@ -693,7 +702,8 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * example: route1=8.8.8.0/24,10.1.1.1,77 * route2=7.7.0.0/16 * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: routes * variable: ADDRESS1, NETMASK1, GATEWAY1, METRIC1, OPTIONS1, ... * description: List of static routes. They are not stored in ifcfg-* file, @@ -787,6 +797,17 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * ---end--- */ + /* ---ifcfg-rh--- + * property: auto-route-ext-gw + * variable: IPV4_AUTO_ROUTE_EXT_GW(+) + * default: yes + * 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. + * ---end--- + */ + /** * NMSettingIP4Config:dhcp-client-id: * @@ -860,6 +881,7 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * variable: DHCP_HOSTNAME_FLAGS * description: flags for the DHCP hostname and FQDN properties * example: DHCP_HOSTNAME_FLAGS=5 + * ---end--- */ /** @@ -961,11 +983,11 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_DNS), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("au"), - .compare_fcn = _nm_setting_property_compare_fcn_default, - .to_dbus_fcn = ip4_dns_to_dbus, - .typdata_from_dbus.gprop_fcn = ip4_dns_from_dbus, - .from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop, - .from_dbus_is_full = TRUE), ); + .compare_fcn = _nm_setting_ip_config_compare_fcn_dns, + .to_dbus_fcn = ip4_dns_to_dbus, + .from_dbus_fcn = ip4_dns_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: addresses @@ -995,15 +1017,19 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ADDRESSES), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aau"), - .to_dbus_fcn = ip4_addresses_get, + .to_dbus_fcn = ip4_addresses_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_addresses, - .from_dbus_fcn = ip4_addresses_set, )); + .from_dbus_fcn = ip4_addresses_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); _nm_properties_override_dbus( properties_override, "address-labels", NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_STRING_ARRAY, - .to_dbus_fcn = ip4_address_labels_get, - .compare_fcn = _nm_setting_property_compare_fcn_ignore, )); + .to_dbus_fcn = ip4_address_labels_to_dbus, + .compare_fcn = _nm_setting_property_compare_fcn_ignore, + /* from_dbus() is handled by ip4_addresses_from_dbus(). */), + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: address-data @@ -1018,9 +1044,9 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, "address-data", NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip4_address_data_get, + .to_dbus_fcn = ip4_address_data_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .from_dbus_fcn = ip4_address_data_set, )); + .from_dbus_fcn = ip4_address_data_from_dbus, )); /* ---dbus--- * property: routes @@ -1090,7 +1116,11 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * <para><literal>"mtu"</literal> - an unsigned 32 bit integer.</para> * </listitem> * <listitem> - * <para><literal>"onlink"</literal> - a boolean value.</para> + * <para><literal>"onlink"</literal> - a boolean value. The onlink flag + * is ignored for IPv4 routes without a gateway. That also means, + * with a positive "weight" the route cannot merge with ECMP routes + * which are onlink and have a gateway. + * </para> * </listitem> * <listitem> * <para><literal>"quickack"</literal> - a boolean value.</para> @@ -1117,6 +1147,17 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * The default is <literal>unicast</literal>.</para> * </listitem> * <listitem> + * <para><literal>"weight"</literal> - an unsigned 32 bit integer + * ranging from 0 to 256. A non-zero weight indicates that the IPv4 + * route is an ECMP IPv4 route. NetworkManager will automatically + * merge compatible ECMP routes into multi-hop routes. Setting to + * zero or omitting the attribute configures single hop routes that + * won't get merged. If the route finds no merge partner, it is + * configured as single hop route.</para> <para>Note that in + * NetworkManager, currently all nexthops of a ECMP route must share + * the same "onlink" flag in order to be mergable.</para> + * </listitem> + * <listitem> * <para><literal>"window"</literal> - an unsigned 32 bit integer.</para> * </listitem> * </itemizedlist> @@ -1130,9 +1171,11 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ROUTES), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aau"), - .to_dbus_fcn = ip4_routes_get, + .to_dbus_fcn = ip4_routes_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_routes, - .from_dbus_fcn = ip4_routes_set, )); + .from_dbus_fcn = ip4_routes_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: route-data @@ -1151,9 +1194,9 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) properties_override, "route-data", NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip4_route_data_get, + .to_dbus_fcn = ip4_route_data_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .from_dbus_fcn = ip4_route_data_set, )); + .from_dbus_fcn = ip4_route_data_from_dbus, )); /* ---nmcli--- * property: routing-rules diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index 94794d1e..43e2e3c7 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -305,7 +305,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) if (priv->token) { if (priv->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { struct in6_addr i6_token; - char s_token[NM_UTILS_INET_ADDRSTRLEN]; + char s_token[NM_INET_ADDRSTRLEN]; if (inet_pton(AF_INET6, priv->token, &i6_token) != 1 || !_nm_utils_inet6_is_token(&i6_token)) { @@ -320,7 +320,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (g_strcmp0(priv->token, _nm_utils_inet6_ntop(&i6_token, s_token))) + if (g_strcmp0(priv->token, nm_inet6_ntop(&i6_token, s_token))) token_needs_normalization = TRUE; } else { g_set_error_literal(error, @@ -389,21 +389,29 @@ ip6_dns_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) GPtrArray *dns; dns = _nm_setting_ip_config_get_dns_array(NM_SETTING_IP_CONFIG(setting)); - if (nm_g_ptr_array_len(dns) == 0) return NULL; - return _nm_utils_ip6_dns_to_variant((const char *const *) dns->pdata, dns->len); + return nm_utils_dns_to_variant(AF_INET6, (const char *const *) dns->pdata, dns->len); } -static void -ip6_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil) +static gboolean +ip6_dns_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - g_value_take_boxed(to, nm_utils_ip6_dns_from_variant(from)); + gs_strfreev char **strv = NULL; + + if (!_nm_setting_use_legacy_property(setting, connection_dict, "dns", "dns-data")) { + *out_is_modified = FALSE; + return TRUE; + } + + strv = nm_utils_ip6_dns_from_variant(value); + g_object_set(setting, NM_SETTING_IP_CONFIG_DNS, strv, NULL); + return TRUE; } static GVariant * -ip6_addresses_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip6_addresses_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *addrs = NULL; const char *gateway; @@ -414,10 +422,10 @@ ip6_addresses_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip6_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip6_addresses_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *addrs; - char *gateway = NULL; + gs_unref_ptrarray GPtrArray *addrs = NULL; + gs_free char *gateway = NULL; if (!_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) { *out_is_modified = FALSE; @@ -432,13 +440,11 @@ ip6_addresses_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); - g_ptr_array_unref(addrs); - g_free(gateway); return TRUE; } static GVariant * -ip6_address_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip6_address_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *addrs = NULL; @@ -450,9 +456,9 @@ ip6_address_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip6_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip6_address_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *addrs; + gs_unref_ptrarray GPtrArray *addrs = NULL; /* Ignore 'address-data' if we're going to process 'addresses' */ if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) { @@ -462,12 +468,11 @@ ip6_address_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) addrs = nm_utils_ip_addresses_from_variant(value, AF_INET6); g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); - g_ptr_array_unref(addrs); return TRUE; } static GVariant * -ip6_routes_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip6_routes_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *routes = NULL; @@ -476,9 +481,9 @@ ip6_routes_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip6_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip6_routes_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *routes; + gs_unref_ptrarray GPtrArray *routes = NULL; if (!_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) { *out_is_modified = FALSE; @@ -487,12 +492,11 @@ ip6_routes_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) routes = nm_utils_ip6_routes_from_variant(value); g_object_set(setting, property_info->name, routes, NULL); - g_ptr_array_unref(routes); return TRUE; } static GVariant * -ip6_route_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +ip6_route_data_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *routes = NULL; @@ -504,9 +508,9 @@ ip6_route_data_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -ip6_route_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +ip6_route_data_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { - GPtrArray *routes; + gs_unref_ptrarray GPtrArray *routes = NULL; /* Ignore 'route-data' if we're going to process 'routes' */ if (_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data")) { @@ -516,7 +520,6 @@ ip6_route_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) routes = nm_utils_ip_routes_from_variant(value, AF_INET6); g_object_set(setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); - g_ptr_array_unref(routes); return TRUE; } @@ -559,11 +562,13 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) setting_class->verify = verify; setting_ip_config_class->private_offset = g_type_class_get_instance_private_offset(klass); + setting_ip_config_class->is_ipv4 = FALSE; + setting_ip_config_class->addr_family = AF_INET6; /* ---ifcfg-rh--- * property: method * variable: IPV6INIT, IPV6FORWARDING, IPV6_AUTOCONF, DHCPV6C, IPV6_DISABLED - * default: IPV6INIT=yes; IPV6FORWARDING=no; IPV6_AUTOCONF=!IPV6FORWARDING, DHCPV6=no + * default: IPV6INIT=yes; IPV6FORWARDING=no; IPV6_AUTOCONF=!IPV6FORWARDING, DHCPV6=no * description: Method used for IPv6 protocol configuration. * ignore ~ IPV6INIT=no; auto ~ IPV6_AUTOCONF=yes; dhcp ~ IPV6_AUTOCONF=no and DHCPV6C=yes; * disabled ~ IPV6_DISABLED=yes @@ -576,10 +581,11 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) * description: List of DNS servers. * example: dns=2001:4860:4860::8888;2001:4860:4860::8844; * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: dns * variable: DNS1, DNS2, ... - * format: string + * format: string * description: List of DNS servers. NetworkManager uses the variables both * for IPv4 and IPv6. * ---end--- @@ -588,7 +594,7 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) /* ---ifcfg-rh--- * property: dns-search * variable: IPV6_DOMAIN(+) - * format: string (space-separated domains) + * format: string (space-separated domains) * description: List of DNS search domains. * ---end--- */ @@ -600,7 +606,8 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) * description: List of static IP addresses. * example: address1=abbe::cafe/96 address2=2001::1234 * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: addresses * variable: IPV6ADDR, IPV6ADDR_SECONDARIES * description: List of static IP addresses. @@ -616,7 +623,8 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) * description: Gateway IP addresses as a string. * example: gateway=abbe::1 * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: gateway * variable: IPV6_DEFAULTGW * description: Gateway IP address. @@ -631,7 +639,8 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) * description: List of IP routes. * example: route1=2001:4860:4860::/64,2620:52:0:2219:222:68ff:fe11:5403 * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: routes * variable: (none) * description: List of static routes. They are not stored in ifcfg-* file, @@ -732,6 +741,17 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) * ---end--- */ + /* ---ifcfg-rh--- + * property: auto-route-ext-gw + * variable: IPV6_AUTO_ROUTE_EXT_GW(+) + * default: yes + * 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. + * ---end--- + */ + /** * NMSettingIP6Config:ip6-privacy: * @@ -869,7 +889,7 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) * Since: 1.24 **/ /* ---ifcfg-rh--- - * property: dhcp-timeout + * property: ra-timeout * variable: IPV6_RA_TIMEOUT(+) * description: A timeout for waiting Router Advertisements in seconds. * example: IPV6_RA_TIMEOUT=10 @@ -972,11 +992,11 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_DNS), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aay"), - .compare_fcn = _nm_setting_property_compare_fcn_default, - .to_dbus_fcn = ip6_dns_to_dbus, - .typdata_from_dbus.gprop_fcn = ip6_dns_from_dbus, - .from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop, - .from_dbus_is_full = TRUE)); + .compare_fcn = _nm_setting_ip_config_compare_fcn_dns, + .to_dbus_fcn = ip6_dns_to_dbus, + .from_dbus_fcn = ip6_dns_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE); /* ---dbus--- * property: addresses @@ -1006,9 +1026,11 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ADDRESSES), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("a(ayuay)"), - .to_dbus_fcn = ip6_addresses_get, + .to_dbus_fcn = ip6_addresses_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_addresses, - .from_dbus_fcn = ip6_addresses_set, )); + .from_dbus_fcn = ip6_addresses_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: address-data @@ -1023,9 +1045,9 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, "address-data", NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip6_address_data_get, + .to_dbus_fcn = ip6_address_data_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .from_dbus_fcn = ip6_address_data_set, )); + .from_dbus_fcn = ip6_address_data_from_dbus, )); /* ---dbus--- * property: routes @@ -1124,9 +1146,11 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ROUTES), NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("a(ayuayu)"), - .to_dbus_fcn = ip6_routes_get, + .to_dbus_fcn = ip6_routes_to_dbus, .compare_fcn = _nm_setting_ip_config_compare_fcn_routes, - .from_dbus_fcn = ip6_routes_set, )); + .from_dbus_fcn = ip6_routes_from_dbus, ), + .to_dbus_only_in_manager_process = TRUE, + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: route-data @@ -1145,9 +1169,9 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) properties_override, "route-data", NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = ip6_route_data_get, + .to_dbus_fcn = ip6_route_data_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .from_dbus_fcn = ip6_route_data_set, )); + .from_dbus_fcn = ip6_route_data_from_dbus, )); /* ---nmcli--- * property: routing-rules diff --git a/src/libnm-core-impl/nm-setting-loopback.c b/src/libnm-core-impl/nm-setting-loopback.c new file mode 100644 index 00000000..1451b411 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-loopback.c @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2022 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-loopback.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-loopback + * @short_description: Describes connection properties for loopback interfaces + * + * The #NMSettingLoopback object is a #NMSetting subclass that describes properties + * necessary for connection to loopback devices + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingLoopback, PROP_MTU, ); + +typedef struct { + guint32 mtu; +} NMSettingLoopbackPrivate; + +/** + * NMSettingLoopback: + * + * Loopback Link Settings + * + * Since: 1.42 + */ +struct _NMSettingLoopback { + NMSetting parent; + NMSettingLoopbackPrivate _priv; +}; + +struct _NMSettingLoopbackClass { + NMSettingClass parent; +}; + +#define NM_SETTING_LOOPBACK_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMSettingLoopback, NM_IS_SETTING_LOOPBACK) + +G_DEFINE_TYPE(NMSettingLoopback, nm_setting_loopback, NM_TYPE_SETTING) + +/*****************************************************************************/ + +/** + * nm_setting_loopback_get_mtu: + * @setting: the #NMSettingLoopback + * + * Returns: the #NMSettingLoopback:mtu property of the setting + * + * Since: 1.42 + **/ +guint32 +nm_setting_loopback_get_mtu(NMSettingLoopback *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_LOOPBACK(setting), 0); + + return NM_SETTING_LOOPBACK_GET_PRIVATE(setting)->mtu; +} + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + if (connection) { + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + NMSettingConnection *s_con; + const char *method; + + if ((s_ip4 = nm_connection_get_setting_ip4_config(connection))) { + if ((method = nm_setting_ip_config_get_method(s_ip4)) + && !NM_IN_STRSET(method, + NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("ipv4 method \"%s\" is not supported for loopback"), + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_METHOD); + return FALSE; + } + if (!NM_IN_SET(nm_setting_ip4_config_get_link_local(NM_SETTING_IP4_CONFIG(s_ip4)), + NM_SETTING_IP4_LL_DEFAULT, + NM_SETTING_IP4_LL_AUTO, + NM_SETTING_IP4_LL_DISABLED)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("ipv4.link-local cannot be enabled for loopback")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_LINK_LOCAL); + return FALSE; + } + } + if ((s_ip6 = nm_connection_get_setting_ip6_config(connection))) { + if ((method = nm_setting_ip_config_get_method(s_ip6)) + && !NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("ipv6 method \"%s\" is not supported for loopback"), + method); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_METHOD); + return FALSE; + } + } + + if ((s_con = nm_connection_get_setting_connection(connection))) { + if (nm_setting_connection_get_slave_type(s_con) + || nm_setting_connection_get_master(s_con)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("a loopback profile cannot be a port")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_CONNECTION_SETTING_NAME, + nm_setting_connection_get_slave_type(s_con) + ? NM_SETTING_CONNECTION_SLAVE_TYPE + : NM_SETTING_CONNECTION_MASTER); + return FALSE; + } + } + } + return TRUE; +} + +/*****************************************************************************/ + +static void +nm_setting_loopback_init(NMSettingLoopback *setting) +{} + +/** + * nm_setting_loopback_new: + * + * Creates a new #NMSettingLoopback object with default values. + * + * Returns: (transfer full): the new empty #NMSettingLoopback object + * + * Since: 1.42 + **/ +NMSetting * +nm_setting_loopback_new(void) +{ + return g_object_new(NM_TYPE_SETTING_LOOPBACK, NULL); +} + +static void +nm_setting_loopback_class_init(NMSettingLoopbackClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray *properties_override = _nm_sett_info_property_override_create_array(); + + object_class->get_property = _nm_setting_property_get_property_direct; + object_class->set_property = _nm_setting_property_set_property_direct; + + setting_class->verify = verify; + + /** + * NMSettingLoopback:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple Ethernet frames. + * + * Since: 1.42 + **/ + /* ---ifcfg-rh--- + * property: mtu + * variable: MTU + * description: MTU of the interface. + * ---end--- + */ + _nm_setting_property_define_direct_uint32(properties_override, + obj_properties, + NM_SETTING_LOOPBACK_MTU, + PROP_MTU, + 0, + G_MAXUINT32, + 0, + NM_SETTING_PARAM_FUZZY_IGNORE, + NMSettingLoopback, + _priv.mtu); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, + NM_META_SETTING_TYPE_LOOPBACK, + NULL, + properties_override, + 0); +} diff --git a/src/libnm-core-impl/nm-setting-macsec.c b/src/libnm-core-impl/nm-setting-macsec.c index 1463fd92..bf48f049 100644 --- a/src/libnm-core-impl/nm-setting-macsec.c +++ b/src/libnm-core-impl/nm-setting-macsec.c @@ -215,13 +215,13 @@ nm_setting_macsec_get_send_sci(NMSettingMacsec *setting) } static GPtrArray * -need_secrets(NMSetting *setting) +need_secrets(NMSetting *setting, gboolean check_rerequest) { NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE(setting); GPtrArray *secrets = NULL; if (priv->mode == NM_SETTING_MACSEC_MODE_PSK) { - if (!priv->mka_cak + if ((check_rerequest || !priv->mka_cak) && !NM_FLAGS_HAS(priv->mka_cak_flags, NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { secrets = g_ptr_array_sized_new(1); g_ptr_array_add(secrets, NM_SETTING_MACSEC_MKA_CAK); diff --git a/src/libnm-core-impl/nm-setting-ovs-bridge.c b/src/libnm-core-impl/nm-setting-ovs-bridge.c index 7dc9fda4..8e850157 100644 --- a/src/libnm-core-impl/nm-setting-ovs-bridge.c +++ b/src/libnm-core-impl/nm-setting-ovs-bridge.c @@ -120,7 +120,7 @@ nm_setting_ovs_bridge_get_stp_enable(NMSettingOvsBridge *self) * * Returns: the #NMSettingOvsBridge:datapath_type property of the setting * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ const char * nm_setting_ovs_bridge_get_datapath_type(NMSettingOvsBridge *self) diff --git a/src/libnm-core-impl/nm-setting-ovs-dpdk.c b/src/libnm-core-impl/nm-setting-ovs-dpdk.c index e26f918b..87e9a3e8 100644 --- a/src/libnm-core-impl/nm-setting-ovs-dpdk.c +++ b/src/libnm-core-impl/nm-setting-ovs-dpdk.c @@ -22,7 +22,7 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_DEVARGS, PROP_N_RXQ, ); +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_DEVARGS, PROP_N_RXQ, PROP_N_RXQ_DESC, PROP_N_TXQ_DESC, ); /** * NMSettingOvsDpdk: @@ -34,6 +34,8 @@ struct _NMSettingOvsDpdk { char *devargs; guint32 n_rxq; + guint32 n_rxq_desc; + guint32 n_txq_desc; }; struct _NMSettingOvsDpdkClass { @@ -76,6 +78,72 @@ nm_setting_ovs_dpdk_get_n_rxq(NMSettingOvsDpdk *self) return self->n_rxq; } +/** + * nm_setting_ovs_dpdk_get_n_rxq_desc: + * @self: the #NMSettingOvsDpdk + * + * Returns: the #NMSettingOvsDpdk:n-rxq-desc property of the setting + * + * Since: 1.42 + **/ +guint32 +nm_setting_ovs_dpdk_get_n_rxq_desc(NMSettingOvsDpdk *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_DPDK(self), 0); + + return self->n_rxq_desc; +} + +/** + * nm_setting_ovs_dpdk_get_n_txq_desc: + * @self: the #NMSettingOvsDpdk + * + * Returns: the #NMSettingOvsDpdk:n-txq-desc property of the setting + * + * Since: 1.42 + **/ +guint32 +nm_setting_ovs_dpdk_get_n_txq_desc(NMSettingOvsDpdk *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_DPDK(self), 0); + + return self->n_txq_desc; +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsDpdk *self = NM_SETTING_OVS_DPDK(setting); + + if (self->n_rxq_desc != 0 && !nm_utils_is_power_of_two(self->n_rxq_desc)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("must be a power of two")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_DPDK_SETTING_NAME, + NM_SETTING_OVS_DPDK_N_RXQ_DESC); + return FALSE; + } + + if (self->n_txq_desc != 0 && !nm_utils_is_power_of_two(self->n_txq_desc)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("must be a power of two")); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_DPDK_SETTING_NAME, + NM_SETTING_OVS_DPDK_N_TXQ_DESC); + return FALSE; + } + + return TRUE; +} + /*****************************************************************************/ static void @@ -107,6 +175,8 @@ nm_setting_ovs_dpdk_class_init(NMSettingOvsDpdkClass *klass) object_class->get_property = _nm_setting_property_get_property_direct; object_class->set_property = _nm_setting_property_set_property_direct; + setting_class->verify = verify; + /** * NMSettingOvsDpdk:devargs: * @@ -142,6 +212,50 @@ nm_setting_ovs_dpdk_class_init(NMSettingOvsDpdkClass *klass) NMSettingOvsDpdk, n_rxq); + /** + * NMSettingOvsDpdk:n-rxq-desc: + * + * The rx queue size (number of rx descriptors) for DPDK ports. + * Must be zero or a power of 2 between 1 and 4096, and supported + * by the hardware. Defaults to zero which means to leave the + * parameter in OVS unspecified and effectively configures 2048 + * descriptors. + * + * Since: 1.42 + **/ + _nm_setting_property_define_direct_uint32(properties_override, + obj_properties, + NM_SETTING_OVS_DPDK_N_RXQ_DESC, + PROP_N_RXQ_DESC, + 0, + 4096, + 0, + NM_SETTING_PARAM_INFERRABLE, + NMSettingOvsDpdk, + n_rxq_desc); + + /** + * NMSettingOvsDpdk:n-txq-desc: + * + * The tx queue size (number of tx descriptors) for DPDK ports. + * Must be zero or a power of 2 between 1 and 4096, and supported + * by the hardware. Defaults to zero which means to leave the + * parameter in OVS unspecified and effectively configures 2048 + * descriptors. + * + * Since: 1.42 + **/ + _nm_setting_property_define_direct_uint32(properties_override, + obj_properties, + NM_SETTING_OVS_DPDK_N_TXQ_DESC, + PROP_N_TXQ_DESC, + 0, + 4096, + 0, + NM_SETTING_PARAM_INFERRABLE, + NMSettingOvsDpdk, + n_txq_desc); + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); _nm_setting_class_commit(setting_class, diff --git a/src/libnm-core-impl/nm-setting-ovs-external-ids.c b/src/libnm-core-impl/nm-setting-ovs-external-ids.c index f4e31f81..54684380 100644 --- a/src/libnm-core-impl/nm-setting-ovs-external-ids.c +++ b/src/libnm-core-impl/nm-setting-ovs-external-ids.c @@ -10,6 +10,7 @@ #include "nm-setting-private.h" #include "nm-utils-private.h" #include "nm-connection-private.h" +#include "nm-setting-ovs-other-config.h" #define MAX_NUM_KEYS 256 @@ -53,15 +54,6 @@ G_DEFINE_TYPE(NMSettingOvsExternalIDs, nm_setting_ovs_external_ids, NM_TYPE_SETT /*****************************************************************************/ -static gboolean -_exid_key_char_is_regular(char ch) -{ - /* allow words of printable characters, plus some - * special characters, for example to support base64 encoding. */ - return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') - || NM_IN_SET(ch, '-', '_', '+', '/', '=', '.'); -} - /** * nm_setting_ovs_external_ids_check_key: * @key: (allow-none): the key to check @@ -105,7 +97,7 @@ nm_setting_ovs_external_ids_check_key(const char *key, GError **error) _("key must be UTF8")); return FALSE; } - if (!NM_STRCHAR_ALL(key, ch, _exid_key_char_is_regular(ch))) { + if (!NM_STRCHAR_ALL(key, ch, nm_ascii_is_regular_char(ch))) { /* Probably OVS is more forgiving about what makes a valid key for * an external-id. However, we are strict (at least, for now). */ g_set_error_literal(error, @@ -127,6 +119,56 @@ nm_setting_ovs_external_ids_check_key(const char *key, GError **error) return TRUE; } +gboolean +_nm_setting_ovs_verify_connection_type(GType gtype, NMConnection *connection, GError **error) +{ + NMSettingConnection *s_con; + const char *type; + const char *slave_type; + + nm_assert(!connection || NM_IS_CONNECTION(connection)); + nm_assert(NM_IN_SET(gtype, NM_TYPE_SETTING_OVS_EXTERNAL_IDS, NM_TYPE_SETTING_OVS_OTHER_CONFIG)); + nm_assert(!error || !*error); + + if (!connection) { + /* We don't know. It's valid. */ + return TRUE; + } + + type = nm_connection_get_connection_type(connection); + if (!type) { + NMSetting *s_base; + + s_base = _nm_connection_find_base_type_setting(connection); + if (s_base) + type = nm_setting_get_name(s_base); + } + if (NM_IN_STRSET(type, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME)) + return TRUE; + + if ((s_con = nm_connection_get_setting_connection(connection)) + && _nm_connection_detect_slave_type_full(s_con, + connection, + &slave_type, + NULL, + NULL, + NULL, + NULL) + && nm_streq0(slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) + return TRUE; + + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("OVS %s can only be added to a profile of type OVS " + "bridge/port/interface or to OVS system interface"), + gtype == NM_TYPE_SETTING_OVS_EXTERNAL_IDS ? "external-ids" : "other-config"); + return FALSE; +} + /** * nm_setting_ovs_external_ids_check_val: * @val: (allow-none): the value to check @@ -204,6 +246,8 @@ nm_setting_ovs_external_ids_get_data_keys(NMSettingOvsExternalIDs *setting, guin NMSettingOvsExternalIDs *self = setting; NMSettingOvsExternalIDsPrivate *priv; + NM_SET_OUT(out_len, 0); + g_return_val_if_fail(NM_IS_SETTING_OVS_EXTERNAL_IDS(self), NULL); priv = NM_SETTING_OVS_EXTERNAL_IDS_GET_PRIVATE(self); @@ -302,12 +346,16 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) if (priv->data) { gs_free_error GError *local = NULL; - GHashTableIter iter; - const char *key; - const char *val; + const char *const *keys; + guint len; + guint i; + + keys = nm_setting_ovs_external_ids_get_data_keys(self, &len); + + for (i = 0; i < len; i++) { + const char *key = keys[i]; + const char *val = g_hash_table_lookup(priv->data, key); - g_hash_table_iter_init(&iter, priv->data); - while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { if (!nm_setting_ovs_external_ids_check_key(key, &local)) { g_set_error(error, NM_CONNECTION_ERROR, @@ -336,7 +384,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("maximum number of user data entries reached (%u instead of %u)"), + _("maximum number of entries reached (%u instead of %u)"), g_hash_table_size(priv->data), (unsigned) MAX_NUM_KEYS); g_prefix_error(error, @@ -346,44 +394,10 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (connection) { - NMSettingConnection *s_con; - const char *type; - const char *slave_type; - - type = nm_connection_get_connection_type(connection); - if (!type) { - NMSetting *s_base; - - s_base = _nm_connection_find_base_type_setting(connection); - if (s_base) - type = nm_setting_get_name(s_base); - } - if (NM_IN_STRSET(type, - NM_SETTING_OVS_BRIDGE_SETTING_NAME, - NM_SETTING_OVS_PORT_SETTING_NAME, - NM_SETTING_OVS_INTERFACE_SETTING_NAME)) - goto connection_type_is_good; - - if ((s_con = nm_connection_get_setting_connection(connection)) - && _nm_connection_detect_slave_type_full(s_con, - connection, - &slave_type, - NULL, - NULL, - NULL, - NULL) - && nm_streq0(slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) - goto connection_type_is_good; - - g_set_error_literal(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("OVS external IDs can only be added to a profile of type OVS " - "bridge/port/interface or to OVS system interface")); + if (!_nm_setting_ovs_verify_connection_type(NM_TYPE_SETTING_OVS_EXTERNAL_IDS, + connection, + error)) return FALSE; - } -connection_type_is_good: return TRUE; } @@ -519,7 +533,7 @@ nm_setting_ovs_external_ids_class_init(NMSettingOvsExternalIDsClass *klass) /** * NMSettingOvsExternalIDs:data: (type GHashTable(utf8,utf8)) * - * A dictionary of key/value pairs with exernal-ids for OVS. + * A dictionary of key/value pairs with external-ids for OVS. * * Since: 1.30 **/ diff --git a/src/libnm-core-impl/nm-setting-ovs-interface.c b/src/libnm-core-impl/nm-setting-ovs-interface.c index 6554f520..34e66480 100644 --- a/src/libnm-core-impl/nm-setting-ovs-interface.c +++ b/src/libnm-core-impl/nm-setting-ovs-interface.c @@ -21,7 +21,7 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_TYPE, ); +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_TYPE, PROP_OFPORT_REQUEST, ); /** * NMSettingOvsInterface: @@ -31,7 +31,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_TYPE, ); struct _NMSettingOvsInterface { NMSetting parent; - char *type; + char *type; + guint32 ofport_request; }; struct _NMSettingOvsInterfaceClass { @@ -58,6 +59,22 @@ nm_setting_ovs_interface_get_interface_type(NMSettingOvsInterface *self) return self->type; } +/** + * nm_setting_ovs_interface_get_ofport_request: + * @self: the #NMSettingOvsInterface + * + * Returns: id of the preassigned ovs port + * + * Since: 1.42 + **/ +guint32 +nm_setting_ovs_interface_get_ofport_request(NMSettingOvsInterface *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_INTERFACE(self), 0); + + return self->ofport_request; +} + /*****************************************************************************/ int @@ -378,6 +395,27 @@ nm_setting_ovs_interface_class_init(NMSettingOvsInterfaceClass *klass) NM_SETTING_PARAM_INFERRABLE, NMSettingOvsInterface, type); + /** + * NMSettingOvsInterface:ofport-request: + * + * Open vSwitch openflow port number. + * Defaults to zero which means that port number will not be specified + * and it will be chosen randomly by ovs. OpenFlow ports are the network interfaces + * for passing packets between OpenFlow processing and the rest of the network. + * OpenFlow switches connect logically to each other via their OpenFlow ports. + * + * Since: 1.42 + **/ + _nm_setting_property_define_direct_uint32(properties_override, + obj_properties, + NM_SETTING_OVS_INTERFACE_OFPORT_REQUEST, + PROP_OFPORT_REQUEST, + 0, + 65279, + 0, + NM_SETTING_PARAM_INFERRABLE, + NMSettingOvsInterface, + ofport_request); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-ovs-other-config.c b/src/libnm-core-impl/nm-setting-ovs-other-config.c new file mode 100644 index 00000000..ca46ae95 --- /dev/null +++ b/src/libnm-core-impl/nm-setting-ovs-other-config.c @@ -0,0 +1,403 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2017 - 2020, 2022 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "nm-setting-ovs-other-config.h" + +#include "nm-setting-private.h" +#include "nm-utils-private.h" +#include "nm-connection-private.h" + +#define MAX_NUM_KEYS 256 + +/*****************************************************************************/ + +/** + * SECTION:nm-setting-ovs-other-config + * @short_description: Other-config settings for OVS + * + * The #NMSettingOvsOtherConfig object is a #NMSetting subclass that allows to + * configure other_config settings for OVS. See also "other_config" in the + * "ovs-vswitchd.conf.db" manual for the keys that OVS supports. + **/ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingOvsOtherConfig, PROP_DATA, ); + +typedef struct { + GHashTable *data; + const char **data_keys; +} NMSettingOvsOtherConfigPrivate; + +/** + * NMSettingOvsOtherConfig: + * + * OVS Other Config Settings + * + * Since: 1.42 + */ +struct _NMSettingOvsOtherConfig { + NMSetting parent; + NMSettingOvsOtherConfigPrivate _priv; +}; + +struct _NMSettingOvsOtherConfigClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE(NMSettingOvsOtherConfig, nm_setting_ovs_other_config, NM_TYPE_SETTING) + +#define NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMSettingOvsOtherConfig, NM_IS_SETTING_OVS_OTHER_CONFIG) + +/*****************************************************************************/ + +static GHashTable * +_create_data_hash(void) +{ + return g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); +} + +GHashTable * +_nm_setting_ovs_other_config_get_data(NMSettingOvsOtherConfig *self) +{ + return NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self)->data; +} + +/** + * nm_setting_ovs_other_config_get_data_keys: + * @setting: the #NMSettingOvsOtherConfig + * @out_len: (out): the length of the returned array + * + * Returns: (array length=out_len) (transfer none): a + * %NULL-terminated array containing each key from the table. + * + * Since: 1.42 + **/ +const char *const * +nm_setting_ovs_other_config_get_data_keys(NMSettingOvsOtherConfig *setting, guint *out_len) +{ + NMSettingOvsOtherConfig *self = setting; + NMSettingOvsOtherConfigPrivate *priv; + + NM_SET_OUT(out_len, 0); + + g_return_val_if_fail(NM_IS_SETTING_OVS_OTHER_CONFIG(self), NULL); + + priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self); + + if (priv->data_keys) { + NM_SET_OUT(out_len, g_hash_table_size(priv->data)); + return priv->data_keys; + } + + priv->data_keys = nm_strdict_get_keys(priv->data, TRUE, out_len); + + /* don't return %NULL, but hijack the @data_keys fields as a pseudo + * empty strv array. */ + return priv->data_keys ?: ((const char **) &priv->data_keys); +} + +/*****************************************************************************/ + +/** + * nm_setting_ovs_other_config_get_data: + * @setting: the #NMSettingOvsOtherConfig instance + * @key: the other-config to lookup + * + * Since: 1.42 + * + * Returns: (transfer none): the value associated with @key or %NULL if no such + * value exists. + */ +const char * +nm_setting_ovs_other_config_get_data(NMSettingOvsOtherConfig *setting, const char *key) +{ + NMSettingOvsOtherConfig *self = setting; + NMSettingOvsOtherConfigPrivate *priv; + + g_return_val_if_fail(NM_IS_SETTING_OVS_OTHER_CONFIG(self), NULL); + g_return_val_if_fail(key, NULL); + + priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self); + + if (!priv->data) + return NULL; + + return g_hash_table_lookup(priv->data, key); +} + +/** + * nm_setting_ovs_other_config_set_data: + * @setting: the #NMSettingOvsOtherConfig instance + * @key: the key to set + * @val: (allow-none): the value to set or %NULL to clear a key. + * + * Since: 1.42 + */ +void +nm_setting_ovs_other_config_set_data(NMSettingOvsOtherConfig *setting, + const char *key, + const char *val) +{ + NMSettingOvsOtherConfig *self = setting; + NMSettingOvsOtherConfigPrivate *priv; + + g_return_if_fail(NM_IS_SETTING_OVS_OTHER_CONFIG(self)); + + priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self); + + if (!val) { + if (priv->data && g_hash_table_remove(priv->data, key)) + goto out_changed; + return; + } + + if (priv->data) { + const char *val2; + + if (g_hash_table_lookup_extended(priv->data, key, NULL, (gpointer *) &val2)) { + if (nm_streq(val, val2)) + return; + } + } else + priv->data = _create_data_hash(); + + g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); + +out_changed: + nm_clear_g_free(&priv->data_keys); + _notify(self, PROP_DATA); +} + +/*****************************************************************************/ + +static gboolean +verify(NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsOtherConfig *self = NM_SETTING_OVS_OTHER_CONFIG(setting); + NMSettingOvsOtherConfigPrivate *priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self); + + if (priv->data) { + gs_free_error GError *local = NULL; + const char *const *keys; + guint len; + guint i; + + keys = nm_setting_ovs_other_config_get_data_keys(self, &len); + + for (i = 0; i < len; i++) { + const char *key = keys[i]; + const char *val = g_hash_table_lookup(priv->data, key); + + if (!nm_setting_ovs_other_config_check_key(key, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid key \"%s\": %s"), + key, + local->message); + } else if (!nm_setting_ovs_other_config_check_val(val, &local)) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + _("invalid value for \"%s\": %s"), + key, + local->message); + } else + continue; + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME, + NM_SETTING_OVS_OTHER_CONFIG_DATA); + return FALSE; + } + } + + if (priv->data && g_hash_table_size(priv->data) > MAX_NUM_KEYS) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("maximum number of entries reached (%u instead of %u)"), + g_hash_table_size(priv->data), + (unsigned) MAX_NUM_KEYS); + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_OTHER_CONFIG_SETTING_NAME, + NM_SETTING_OVS_OTHER_CONFIG_DATA); + return FALSE; + } + + if (!_nm_setting_ovs_verify_connection_type(NM_TYPE_SETTING_OVS_OTHER_CONFIG, + connection, + error)) + return FALSE; + + return TRUE; +} + +static NMTernary +compare_fcn_data(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil) +{ + NMSettingOvsOtherConfigPrivate *priv; + NMSettingOvsOtherConfigPrivate *pri2; + + if (NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) + return NM_TERNARY_DEFAULT; + + if (!set_b) + return TRUE; + + priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(NM_SETTING_OVS_OTHER_CONFIG(set_a)); + pri2 = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(NM_SETTING_OVS_OTHER_CONFIG(set_b)); + return nm_utils_hashtable_equal(priv->data, pri2->data, TRUE, g_str_equal); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingOvsOtherConfig *self = NM_SETTING_OVS_OTHER_CONFIG(object); + NMSettingOvsOtherConfigPrivate *priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self); + GHashTableIter iter; + GHashTable *data; + const char *key; + const char *val; + + switch (prop_id) { + case PROP_DATA: + data = _create_data_hash(); + if (priv->data) { + g_hash_table_iter_init(&iter, priv->data); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert(data, g_strdup(key), g_strdup(val)); + } + g_value_take_boxed(value, data); + 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) +{ + NMSettingOvsOtherConfig *self = NM_SETTING_OVS_OTHER_CONFIG(object); + NMSettingOvsOtherConfigPrivate *priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self); + + switch (prop_id) { + case PROP_DATA: + { + gs_unref_hashtable GHashTable *old = NULL; + GHashTableIter iter; + GHashTable *data; + const char *key; + const char *val; + + nm_clear_g_free(&priv->data_keys); + + old = g_steal_pointer(&priv->data); + + data = g_value_get_boxed(value); + if (nm_g_hash_table_size(data) <= 0) + return; + + priv->data = _create_data_hash(); + g_hash_table_iter_init(&iter, data); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) + g_hash_table_insert(priv->data, g_strdup(key), g_strdup(val)); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_other_config_init(NMSettingOvsOtherConfig *self) +{} + +/** + * nm_setting_ovs_other_config_new: + * + * Creates a new #NMSettingOvsOtherConfig object with default values. + * + * Returns: (transfer full) (type NMSettingOvsOtherConfig): the new empty + * #NMSettingOvsOtherConfig object + * + * Since: 1.42 + */ +NMSetting * +nm_setting_ovs_other_config_new(void) +{ + return g_object_new(NM_TYPE_SETTING_OVS_OTHER_CONFIG, NULL); +} + +static void +finalize(GObject *object) +{ + NMSettingOvsOtherConfig *self = NM_SETTING_OVS_OTHER_CONFIG(object); + NMSettingOvsOtherConfigPrivate *priv = NM_SETTING_OVS_OTHER_CONFIG_GET_PRIVATE(self); + + g_free(priv->data_keys); + if (priv->data) + g_hash_table_unref(priv->data); + + G_OBJECT_CLASS(nm_setting_ovs_other_config_parent_class)->finalize(object); +} + +static void +nm_setting_ovs_other_config_class_init(NMSettingOvsOtherConfigClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + NMSettingClass *setting_class = NM_SETTING_CLASS(klass); + GArray *properties_override = _nm_sett_info_property_override_create_array(); + + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingOvsOtherConfig:data: (type GHashTable(utf8,utf8)) + * + * A dictionary of key/value pairs with other_config settings for OVS. + * See also "other_config" in the "ovs-vswitchd.conf.db" manual for the keys + * that OVS supports. + * + * Since: 1.42 + **/ + obj_properties[PROP_DATA] = g_param_spec_boxed(NM_SETTING_OVS_OTHER_CONFIG_DATA, + "", + "", + G_TYPE_HASH_TABLE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_DATA], + NM_SETT_INFO_PROPERT_TYPE_GPROP(NM_G_VARIANT_TYPE("a{ss}"), + .typdata_from_dbus.gprop_fcn = _nm_utils_strdict_from_dbus, + .typdata_to_dbus.gprop_type = + NM_SETTING_PROPERTY_TO_DBUS_FCN_GPROP_TYPE_STRDICT, + .compare_fcn = compare_fcn_data, + .from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop, + .from_dbus_is_full = TRUE)); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit(setting_class, + NM_META_SETTING_TYPE_OVS_OTHER_CONFIG, + NULL, + properties_override, + 0); +} diff --git a/src/libnm-core-impl/nm-setting-ovs-port.c b/src/libnm-core-impl/nm-setting-ovs-port.c index ab9c0a11..190f1e5d 100644 --- a/src/libnm-core-impl/nm-setting-ovs-port.c +++ b/src/libnm-core-impl/nm-setting-ovs-port.c @@ -21,12 +21,14 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_VLAN_MODE, - PROP_TAG, - PROP_LACP, - PROP_BOND_MODE, - PROP_BOND_UPDELAY, - PROP_BOND_DOWNDELAY, ); +NM_GOBJECT_PROPERTIES_DEFINE(NMSettingOvsPort, + PROP_VLAN_MODE, + PROP_TAG, + PROP_TRUNKS, + PROP_LACP, + PROP_BOND_MODE, + PROP_BOND_UPDELAY, + PROP_BOND_DOWNDELAY, ); /** * NMSettingOvsPort: @@ -36,12 +38,13 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_VLAN_MODE, struct _NMSettingOvsPort { NMSetting parent; - char *vlan_mode; - char *lacp; - char *bond_mode; - guint32 tag; - guint32 bond_updelay; - guint32 bond_downdelay; + GPtrArray *trunks; + char *vlan_mode; + char *lacp; + char *bond_mode; + guint32 tag; + guint32 bond_updelay; + guint32 bond_downdelay; }; struct _NMSettingOvsPortClass { @@ -84,6 +87,143 @@ nm_setting_ovs_port_get_tag(NMSettingOvsPort *self) return self->tag; } +/*****************************************************************************/ + +/** + * nm_setting_ovs_port_add_trunk: + * @setting: the #NMSettingOvsPort + * @trunk: the trunk to add + * + * Appends a new trunk range to the setting. + * This takes a reference to @trunk. + * + * Since: 1.42 + **/ +void +nm_setting_ovs_port_add_trunk(NMSettingOvsPort *self, NMRange *trunk) +{ + g_return_if_fail(NM_IS_SETTING_OVS_PORT(self)); + g_return_if_fail(trunk); + + g_ptr_array_add(self->trunks, nm_range_ref(trunk)); + _notify(self, PROP_TRUNKS); +} + +/** + * nm_setting_ovs_port_get_num_trunks: + * @setting: the #NMSettingOvsPort + * + * Returns: the number of trunk ranges + * + * Since: 1.42 + **/ +guint +nm_setting_ovs_port_get_num_trunks(NMSettingOvsPort *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), 0); + + return self->trunks->len; +} + +/** + * nm_setting_ovs_port_get_trunk: + * @setting: the #NMSettingOvsPort + * @idx: index number of the trunk range to return + * + * Returns: (transfer none): the trunk range at index @idx + * + * Since: 1.42 + **/ +NMRange * +nm_setting_ovs_port_get_trunk(NMSettingOvsPort *self, guint idx) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), NULL); + + g_return_val_if_fail(idx < self->trunks->len, NULL); + + return self->trunks->pdata[idx]; +} + +/** + * nm_setting_ovs_port_remove_trunk: + * @setting: the #NMSettingOvsPort + * @idx: index number of the trunk range. + * + * Removes the trunk range at index @idx. + * + * Since: 1.42 + **/ +void +nm_setting_ovs_port_remove_trunk(NMSettingOvsPort *self, guint idx) +{ + g_return_if_fail(NM_IS_SETTING_OVS_PORT(self)); + + g_return_if_fail(idx < self->trunks->len); + + g_ptr_array_remove_index(self->trunks, idx); + _notify(self, PROP_TRUNKS); +} + +/** + * nm_setting_ovs_port_remove_trunk_by_value: + * @setting: the #NMSettingOvsPort + * @start: the trunk range start index + * @end: the trunk range end index + * + * Remove the trunk range with range @start to @end. + * + * Returns: %TRUE if the trunk range was found and removed; %FALSE otherwise + * + * Since: 1.42 + **/ +gboolean +nm_setting_ovs_port_remove_trunk_by_value(NMSettingOvsPort *self, guint start, guint end) +{ + NMRange *trunk; + guint i; + + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), FALSE); + + for (i = 0; i < self->trunks->len; i++) { + trunk = (NMRange *) self->trunks->pdata[i]; + if (trunk->start == start && trunk->end == end) { + g_ptr_array_remove_index(self->trunks, i); + _notify(self, PROP_TRUNKS); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_ovs_port_clear_trunks: + * @setting: the #NMSettingOvsPort + * + * Removes all configured trunk ranges. + * + * Since: 1.42 + **/ +void +nm_setting_ovs_port_clear_trunks(NMSettingOvsPort *self) +{ + g_return_if_fail(NM_IS_SETTING_OVS_PORT(self)); + + if (self->trunks->len != 0) { + g_ptr_array_set_size(self->trunks, 0); + _notify(self, PROP_TRUNKS); + } +} + +const GPtrArray * +_nm_setting_ovs_port_get_trunks_arr(NMSettingOvsPort *self) +{ + g_return_val_if_fail(NM_IS_SETTING_OVS_PORT(self), NULL); + + return self->trunks; +} + +/*****************************************************************************/ + /** * nm_setting_ovs_port_get_lacp: * @self: the #NMSettingOvsPort @@ -151,6 +291,107 @@ nm_setting_ovs_port_get_bond_downdelay(NMSettingOvsPort *self) /*****************************************************************************/ static int +range_cmp(gconstpointer a, gconstpointer b) +{ + const NMRange *range_a = *(const NMRange **) a; + const NMRange *range_b = *(const NMRange **) b; + + return nm_range_cmp(range_a, range_b); +} + +gboolean +_nm_setting_ovs_port_sort_trunks(NMSettingOvsPort *self) +{ + gboolean need_sort = FALSE; + guint i; + + for (i = 1; i < self->trunks->len; i++) { + NMRange *range_prev = self->trunks->pdata[i - 1]; + NMRange *range = self->trunks->pdata[i]; + + if (nm_range_cmp(range_prev, range) > 0) { + need_sort = TRUE; + break; + } + } + + if (need_sort) { + g_ptr_array_sort(self->trunks, range_cmp); + _notify(self, PROP_TRUNKS); + } + + return need_sort; +} + +static gboolean +verify_trunks(GPtrArray *ranges, GError **error) +{ + gs_unref_hashtable GHashTable *h = NULL; + NMRange *range; + guint i; + guint vlan; + + if (!ranges) + return TRUE; + + h = g_hash_table_new(nm_direct_hash, NULL); + + for (i = 0; i < ranges->len; i++) { + range = ranges->pdata[i]; + nm_assert(range->start <= range->end); + + if (range->start > 4095 || range->end > 4095) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("VLANs must be between 0 and 4095")); + return FALSE; + } + + for (vlan = range->start; vlan <= range->end; vlan++) { + if (!nm_g_hash_table_add(h, GUINT_TO_POINTER(vlan))) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("duplicate VLAN %u"), + vlan); + return FALSE; + } + } + } + + return TRUE; +} + +static gboolean +verify_trunks_normalizable(GPtrArray *ranges, GError **error) +{ + guint i; + + nm_assert(verify_trunks(ranges, NULL)); + + if (!ranges || ranges->len <= 1) + return TRUE; + + for (i = 1; i < ranges->len; i++) { + NMRange *range_prev = ranges->pdata[i - 1]; + NMRange *range = ranges->pdata[i]; + + if (nm_range_cmp(range_prev, range) > 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("VLANs %u and %u are not sorted in ascending order"), + (guint) range_prev->start, + (guint) range->start); + return FALSE; + } + } + + return TRUE; +} + +static int verify(NMSetting *setting, NMConnection *connection, GError **error) { NMSettingOvsPort *self = NM_SETTING_OVS_PORT(setting); @@ -208,6 +449,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) "native-tagged", "native-untagged", "trunk", + "dot1q-tunnel", NULL)) { g_set_error(error, NM_CONNECTION_ERROR, @@ -257,14 +499,68 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if (!verify_trunks(self->trunks, error)) { + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_PORT_TRUNKS); + return FALSE; + } + + if (!verify_trunks_normalizable(self->trunks, error)) { + g_prefix_error(error, + "%s.%s: ", + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_PORT_TRUNKS); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + return TRUE; } /*****************************************************************************/ static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT(object); + + switch (prop_id) { + case PROP_TRUNKS: + g_value_take_boxed(value, + _nm_utils_copy_array(self->trunks, + (NMUtilsCopyFunc) nm_range_ref, + (GDestroyNotify) nm_range_unref)); + break; + default: + _nm_setting_property_get_property_direct(object, prop_id, value, pspec); + break; + } +} + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT(object); + + switch (prop_id) { + case PROP_TRUNKS: + g_ptr_array_unref(self->trunks); + self->trunks = _nm_utils_copy_array(g_value_get_boxed(value), + (NMUtilsCopyFunc) nm_range_ref, + (GDestroyNotify) nm_range_unref); + break; + default: + _nm_setting_property_set_property_direct(object, prop_id, value, pspec); + break; + } +} + +static void nm_setting_ovs_port_init(NMSettingOvsPort *self) -{} +{ + self->trunks = g_ptr_array_new_with_free_func((GDestroyNotify) nm_range_unref); +} /** * nm_setting_ovs_port_new: @@ -282,14 +578,25 @@ nm_setting_ovs_port_new(void) } static void +finalize(GObject *object) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT(object); + + g_ptr_array_unref(self->trunks); + + G_OBJECT_CLASS(nm_setting_ovs_port_parent_class)->finalize(object); +} + +static void nm_setting_ovs_port_class_init(NMSettingOvsPortClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); NMSettingClass *setting_class = NM_SETTING_CLASS(klass); GArray *properties_override = _nm_sett_info_property_override_create_array(); - object_class->get_property = _nm_setting_property_get_property_direct; - object_class->set_property = _nm_setting_property_set_property_direct; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; setting_class->verify = verify; @@ -297,7 +604,7 @@ nm_setting_ovs_port_class_init(NMSettingOvsPortClass *klass) * NMSettingOvsPort:vlan-mode: * * The VLAN mode. One of "access", "native-tagged", "native-untagged", - * "trunk" or unset. + * "trunk", "dot1q-tunnel" or unset. * * Since: 1.10 **/ @@ -328,6 +635,31 @@ nm_setting_ovs_port_class_init(NMSettingOvsPortClass *klass) tag); /** + * NMSettingOvsPort:trunks: (type GPtrArray(NMRange)) + * + * A list of VLAN ranges that this port trunks. + * + * The property is valid only for ports with mode "trunk", + * "native-tagged", or "native-untagged port". + * If it is empty, the port trunks all VLANs. + * + * Since: 1.42 + **/ + obj_properties[PROP_TRUNKS] = g_param_spec_boxed(NM_SETTING_OVS_PORT_TRUNKS, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE + | G_PARAM_STATIC_STRINGS); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_TRUNKS], + NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = _nm_utils_ranges_to_dbus, + .compare_fcn = _nm_utils_ranges_cmp, + .from_dbus_fcn = _nm_utils_ranges_from_dbus)); + + /** * NMSettingOvsPort:lacp: * * LACP mode. One of "active", "off", or "passive". diff --git a/src/libnm-core-impl/nm-setting-pppoe.c b/src/libnm-core-impl/nm-setting-pppoe.c index c4a9a89c..5c4f3c28 100644 --- a/src/libnm-core-impl/nm-setting-pppoe.c +++ b/src/libnm-core-impl/nm-setting-pppoe.c @@ -178,12 +178,12 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } static GPtrArray * -need_secrets(NMSetting *setting) +need_secrets(NMSetting *setting, gboolean check_rerequest) { NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE(setting); GPtrArray *secrets = NULL; - if (priv->password) + if (!check_rerequest && priv->password) return NULL; if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) { diff --git a/src/libnm-core-impl/nm-setting-private.h b/src/libnm-core-impl/nm-setting-private.h index 38b233e9..26a31b1e 100644 --- a/src/libnm-core-impl/nm-setting-private.h +++ b/src/libnm-core-impl/nm-setting-private.h @@ -13,24 +13,69 @@ #include "nm-setting.h" #include "nm-setting-bridge.h" #include "nm-connection.h" +#include "nm-simple-connection.h" #include "nm-core-enum-types.h" #include "libnm-core-intern/nm-core-internal.h" /*****************************************************************************/ +struct _NMRefString; + typedef struct { NMConnection *self; NMSetting *settings[_NM_META_SETTING_TYPE_NUM]; /* D-Bus path of the connection, if any */ - char *path; + struct _NMRefString *path; } NMConnectionPrivate; extern GTypeClass *_nm_simple_connection_class_instance; extern int _nm_simple_connection_private_offset; +#undef NM_IS_SIMPLE_CONNECTION +#define NM_IS_SIMPLE_CONNECTION(self) \ + ({ \ + gconstpointer _self1 = (self); \ + gboolean _result; \ + \ + _result = \ + (_self1 \ + && (((GTypeInstance *) _self1)->g_class == _nm_simple_connection_class_instance)); \ + \ + nm_assert(_result == G_TYPE_CHECK_INSTANCE_TYPE(_self1, NM_TYPE_SIMPLE_CONNECTION)); \ + \ + _result; \ + }) + +#undef NM_IS_CONNECTION +#define NM_IS_CONNECTION(self) \ + ({ \ + gconstpointer _self0 = (self); \ + \ + (_self0 \ + && (NM_IS_SIMPLE_CONNECTION(_self0) \ + || G_TYPE_CHECK_INSTANCE_TYPE(_self0, NM_TYPE_CONNECTION))); \ + }) + +#define _NM_SIMPLE_CONNECTION_GET_CONNECTION_PRIVATE(connection) \ + ({ \ + gpointer _connection_1 = (connection); \ + NMConnectionPrivate *_priv_1; \ + \ + nm_assert(NM_IS_SIMPLE_CONNECTION(_connection_1)); \ + \ + _priv_1 = (void *) (&(((char *) _connection_1)[_nm_simple_connection_private_offset])); \ + \ + nm_assert(_priv_1 \ + == G_TYPE_INSTANCE_GET_PRIVATE(_connection_1, \ + NM_TYPE_SIMPLE_CONNECTION, \ + NMConnectionPrivate)); \ + \ + _priv_1; \ + }) + void _nm_connection_private_clear(NMConnectionPrivate *priv); /*****************************************************************************/ @@ -55,7 +100,7 @@ struct _NMSettingClass { gboolean (*verify_secrets)(NMSetting *setting, NMConnection *connection, GError **error); - GPtrArray *(*need_secrets)(NMSetting *setting); + GPtrArray *(*need_secrets)(NMSetting *setting, gboolean check_rerequest); int (*update_one_secret)(NMSetting *setting, const char *key, GVariant *value, GError **error); @@ -120,11 +165,23 @@ struct _NMSettingIPConfigClass { NMSettingClass parent; /* In the past, this struct was public API. Preserve ABI! */ + union { - gpointer _dummy; + gpointer _dummy1; int private_offset; }; - gpointer padding[7]; + + union { + gpointer _dummy2; + gint8 addr_family; + }; + + union { + gpointer _dummy3; + bool is_ipv4; + }; + + gpointer padding[5]; }; typedef struct { @@ -140,6 +197,7 @@ typedef struct { char *dhcp_hostname; char *dhcp_iaid; gint64 route_metric; + int auto_route_ext_gw; gint32 required_timeout; gint32 dad_timeout; gint32 dhcp_timeout; @@ -155,6 +213,11 @@ typedef struct { void _nm_setting_ip_config_private_init(gpointer self, NMSettingIPConfigPrivate *priv); +#define NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting) \ + (NM_SETTING_IP_CONFIG_GET_CLASS(setting)->addr_family) + +#define NM_SETTING_IP_CONFIG_IS_IPv4(setting) (NM_SETTING_IP_CONFIG_GET_CLASS(setting)->is_ipv4) + /*****************************************************************************/ NMSettingPriority _nm_setting_get_base_type_priority(NMSetting *setting); @@ -240,6 +303,14 @@ typedef struct { /*****************************************************************************/ +struct _NMRange { + int refcount; + guint64 start; + guint64 end; +}; + +/*****************************************************************************/ + #define NM_SETTING_PARAM_NONE 0 /* The property of the #NMSetting should be considered during comparisons that @@ -256,8 +327,9 @@ typedef struct { */ #define NM_SETTING_PARAM_INFERRABLE (1 << (4 + G_PARAM_USER_SHIFT)) -/* This is a legacy property, which clients should not send to the daemon. */ -#define NM_SETTING_PARAM_LEGACY (1 << (5 + G_PARAM_USER_SHIFT)) +/* This flag has no meaning (anymore). It's only kept, because we used it + * on some older versions of libnm. */ +#define NM_SETTING_PARAM_UNUSED1 (1 << (5 + G_PARAM_USER_SHIFT)) /* When a connection is active and gets modified, usually the change * to the settings-connection does not propagate automatically to the @@ -442,10 +514,14 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p .property_type = (p_property_type), \ __VA_ARGS__)) -#define _nm_properties_override_dbus(properties_override, p_name, p_property_type) \ - _nm_properties_override( \ - (properties_override), \ - NM_SETT_INFO_PROPERTY(.name = ("" p_name ""), .property_type = (p_property_type), )) +#define _nm_properties_override_dbus(properties_override, \ + p_name, \ + p_property_type, \ + ... /* extra NMSettInfoProperty fields */) \ + _nm_properties_override((properties_override), \ + NM_SETT_INFO_PROPERTY(.name = ("" p_name ""), \ + .property_type = (p_property_type), \ + __VA_ARGS__)) /*****************************************************************************/ @@ -984,7 +1060,7 @@ gboolean _nm_setting_use_legacy_property(NMSetting *setting, const char *legacy_property, const char *new_property); -GPtrArray *_nm_setting_need_secrets(NMSetting *setting); +GPtrArray *_nm_setting_need_secrets(NMSetting *setting, gboolean check_rerequest); gboolean _nm_setting_should_compare_secret_property(NMSetting *setting, NMSetting *other, @@ -998,15 +1074,26 @@ gboolean _nm_utils_bridge_vlans_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS GVariant *_nm_utils_bridge_vlans_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil); +gboolean _nm_utils_ranges_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil); + +NMTernary _nm_utils_ranges_cmp(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil); + +GVariant *_nm_utils_ranges_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil); + NMTernary _nm_setting_ip_config_compare_fcn_addresses(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil); NMTernary _nm_setting_ip_config_compare_fcn_routes(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil); -gboolean _nm_utils_hwaddr_cloned_not_set(_NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil); +NMTernary _nm_setting_ip_config_compare_fcn_dns(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil); -GVariant *_nm_utils_hwaddr_cloned_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil); +gboolean _nm_sett_info_prop_missing_from_dbus_fcn_cloned_mac_address( + _NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil); + +GVariant * +_nm_sett_info_prop_to_dbus_fcn_cloned_mac_address(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil); -gboolean _nm_utils_hwaddr_cloned_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil); +gboolean +_nm_sett_info_prop_from_dbus_fcn_cloned_mac_address(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil); /*****************************************************************************/ diff --git a/src/libnm-core-impl/nm-setting-serial.c b/src/libnm-core-impl/nm-setting-serial.c index a8201876..6fe3e487 100644 --- a/src/libnm-core-impl/nm-setting-serial.c +++ b/src/libnm-core-impl/nm-setting-serial.c @@ -278,7 +278,8 @@ nm_setting_serial_class_init(NMSettingSerialClass *klass) * 111 ('o') for odd, or 110 ('n') for none. * example: parity=n * ---end--- - * ---dbus--- + */ + /* ---dbus--- * property: parity * format: byte * description: The connection parity: 69 (ASCII 'E') for even parity, diff --git a/src/libnm-core-impl/nm-setting-sriov.c b/src/libnm-core-impl/nm-setting-sriov.c index f9bee21e..091cc0c6 100644 --- a/src/libnm-core-impl/nm-setting-sriov.c +++ b/src/libnm-core-impl/nm-setting-sriov.c @@ -372,7 +372,7 @@ const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[] = { * * Returns: %TRUE if the attribute is valid, %FALSE otherwise * - * Since: 1.42, 1.40.4 + * Since: 1.42 */ gboolean nm_sriov_vf_attribute_validate(const char *name, GVariant *value, gboolean *known, GError **error) diff --git a/src/libnm-core-impl/nm-setting-tc-config.c b/src/libnm-core-impl/nm-setting-tc-config.c index 529bbca1..80135201 100644 --- a/src/libnm-core-impl/nm-setting-tc-config.c +++ b/src/libnm-core-impl/nm-setting-tc-config.c @@ -935,7 +935,7 @@ nm_tc_tfilter_get_parent(NMTCTfilter *tfilter) * * Returns: the action associated with a traffic filter. * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ NMTCAction * nm_tc_tfilter_get_action(NMTCTfilter *tfilter) @@ -956,7 +956,7 @@ nm_tc_tfilter_get_action(NMTCTfilter *tfilter) * * Sets the action associated with a traffic filter. * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ void nm_tc_tfilter_set_action(NMTCTfilter *tfilter, NMTCAction *action) @@ -1475,7 +1475,7 @@ next: } static GVariant * -tc_qdiscs_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +qdiscs_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *qdiscs = NULL; @@ -1484,7 +1484,7 @@ tc_qdiscs_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -tc_qdiscs_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +qdiscs_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *qdiscs = NULL; @@ -1661,7 +1661,7 @@ next: } static GVariant * -tc_tfilters_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +tfilters_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *tfilters = NULL; @@ -1670,7 +1670,7 @@ tc_tfilters_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -tc_tfilters_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +tfilters_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *tfilters = NULL; @@ -1944,8 +1944,8 @@ nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) * <para> * can be used to set a different hash table size, available * from kernel 2.6.39 onwards. The specified divisor must be - * a power of two and cannot be larger than 65536. Default - * value: 1024. + * a power of two and cannot be larger than 65536. + * Default value: 1024. * </para> * </listitem> * </varlistentry> @@ -2083,12 +2083,13 @@ nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) G_TYPE_PTR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS); - _nm_properties_override_gobj(properties_override, - obj_properties[PROP_QDISCS], - NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = tc_qdiscs_get, - .compare_fcn = compare_fcn_qdiscs, - .from_dbus_fcn = tc_qdiscs_set, )); + _nm_properties_override_gobj( + properties_override, + obj_properties[PROP_QDISCS], + NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), + .to_dbus_fcn = qdiscs_to_dbus, + .compare_fcn = compare_fcn_qdiscs, + .from_dbus_fcn = qdiscs_from_dbus, )); /** * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter)) @@ -2107,8 +2108,8 @@ nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) * format: GPtrArray(NMTCTfilter) * description-docbook: * <para> - * Array of TC traffic filters. Traffic control can manage the packet content during - * classification by using filters. + * Array of TC traffic filters. Traffic control can manage the packet content during + * classification by using filters. * </para> * <para> * Each tfilters can be specified by the following attributes: @@ -2206,7 +2207,7 @@ nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) * ---end--- **/ /* ---ifcfg-rh--- - * property: qdiscs + * property: tfilters * variable: FILTER1(+), FILTER2(+), ..., TC_COMMIT(+) * description: Traffic filters to set on the interface. When no * QDISC1, QDISC2, ..., FILTER1, FILTER2, ... keys are present, @@ -2225,9 +2226,9 @@ nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) properties_override, obj_properties[PROP_TFILTERS], NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = tc_tfilters_get, + .to_dbus_fcn = tfilters_to_dbus, .compare_fcn = compare_fcn_tfilter, - .from_dbus_fcn = tc_tfilters_set, )); + .from_dbus_fcn = tfilters_from_dbus, )); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-team.c b/src/libnm-core-impl/nm-setting-team.c index 3eeeb2c3..e6e375e7 100644 --- a/src/libnm-core-impl/nm-setting-team.c +++ b/src/libnm-core-impl/nm-setting-team.c @@ -375,6 +375,8 @@ _nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher) * * Increases the reference count of the object. * + * Since 1.20, ref-counting of #NMTeamLinkWatcher is thread-safe. + * * Since: 1.12 **/ void @@ -390,6 +392,8 @@ nm_team_link_watcher_ref(NMTeamLinkWatcher *watcher) * Decreases the reference count of the object. If the reference count * reaches zero, the object will be destroyed. * + * Since 1.20, ref-counting of #NMTeamLinkWatcher is thread-safe. + * * Since: 1.12 **/ void @@ -1829,7 +1833,8 @@ nm_setting_team_class_init(NMSettingTeamClass *klass) */ _nm_properties_override_dbus(properties_override, "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); + &nm_sett_info_propert_type_deprecated_interface_name, + .dbus_deprecated = TRUE); g_object_class_install_properties(object_class, G_N_ELEMENTS(obj_properties), obj_properties); diff --git a/src/libnm-core-impl/nm-setting-vlan.c b/src/libnm-core-impl/nm-setting-vlan.c index 5f50acdd..696799d8 100644 --- a/src/libnm-core-impl/nm-setting-vlan.c +++ b/src/libnm-core-impl/nm-setting-vlan.c @@ -30,6 +30,7 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMSettingVlan, PROP_PARENT, PROP_ID, PROP_FLAGS, + PROP_PROTOCOL, PROP_INGRESS_PRIORITY_MAP, PROP_EGRESS_PRIORITY_MAP, ); @@ -37,6 +38,7 @@ typedef struct { GSList *ingress_priority_map; GSList *egress_priority_map; char *parent; + char *protocol; guint32 id; guint32 flags; } NMSettingVlanPrivate; @@ -82,6 +84,22 @@ nm_setting_vlan_get_parent(NMSettingVlan *setting) } /** + * nm_setting_vlan_get_protocol: + * @setting: the #NMSettingVlan + * + * Since: 1.42 + * + * Returns: the #NMSettingVlan:protocol property of the setting + **/ +const char * +nm_setting_vlan_get_protocol(NMSettingVlan *setting) +{ + g_return_val_if_fail(NM_IS_SETTING_VLAN(setting), NULL); + + return NM_SETTING_VLAN_GET_PRIVATE(setting)->protocol; +} + +/** * nm_setting_vlan_get_id: * @setting: the #NMSettingVlan * @@ -662,6 +680,16 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if (!NM_IN_STRSET(priv->protocol, NULL, "802.1Q", "802.1ad")) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid VLAN protocol %s: must be '802.1Q' or '802.1ad'"), + priv->protocol); + g_prefix_error(error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PROTOCOL); + return FALSE; + } + if (connection && !s_wired) { /* technically, a VLAN setting does not require an ethernet setting. However, * the ifcfg-rh reader always adds a ethernet setting when reading a vlan setting. @@ -678,13 +706,13 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } static GVariant * -_override_flags_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +vlan_flags_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { return g_variant_new_uint32(nm_setting_vlan_get_flags((NMSettingVlan *) setting)); } static gboolean -_override_flags_not_set(_NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil) +vlan_flags_missing_from_dbus(_NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil) { /* we changed the default value for FLAGS. When an older client * doesn't serialize the property, we assume it is the old default. */ @@ -909,13 +937,39 @@ nm_setting_vlan_class_init(NMSettingVlanClass *klass) properties_override, obj_properties[PROP_FLAGS], NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_UINT32, - .to_dbus_fcn = _override_flags_get, + .to_dbus_fcn = vlan_flags_to_dbus, .compare_fcn = _nm_setting_property_compare_fcn_default, - .missing_from_dbus_fcn = _override_flags_not_set, + .missing_from_dbus_fcn = vlan_flags_missing_from_dbus, .from_dbus_fcn = _nm_setting_property_from_dbus_fcn_gprop, .from_dbus_is_full = TRUE)); /** + * NMSettingVlan:protocol: + * + * Specifies the VLAN protocol to use for encapsulation. + * + * Supported values are: '802.1Q', '802.1ad'. If not specified the default + * value is '802.1Q'. + * + * Since: 1.42 + **/ + /* ---ifcfg-rh--- + * property: protocol + * variable: VLAN_PROTOCOL + * description: VLAN protocol. + * example: VLAN_PROTOCOL="802.1ad" + * ---end--- + */ + _nm_setting_property_define_direct_string(properties_override, + obj_properties, + NM_SETTING_VLAN_PROTOCOL, + PROP_PROTOCOL, + NM_SETTING_PARAM_INFERRABLE, + NMSettingVlanPrivate, + protocol, + .direct_string_is_refstr = TRUE); + + /** * NMSettingVlan:ingress-priority-map: * * For incoming packets, a list of mappings from 802.1p priorities to Linux @@ -965,7 +1019,8 @@ nm_setting_vlan_class_init(NMSettingVlanClass *klass) * but VLAN id from DEVICE takes precedence over VLAN_ID. * example: PHYSDEV=eth0, VLAN_ID=12; or DEVICE=eth0.12 * ---end--- - * ---dbus--- + */ + /* ---dbus--- * property: interface-name * format: string * description: Deprecated in favor of connection.interface-name, but can @@ -975,7 +1030,8 @@ nm_setting_vlan_class_init(NMSettingVlanClass *klass) */ _nm_properties_override_dbus(properties_override, "interface-name", - &nm_sett_info_propert_type_deprecated_interface_name); + &nm_sett_info_propert_type_deprecated_interface_name, + .dbus_deprecated = TRUE, ); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-vpn.c b/src/libnm-core-impl/nm-setting-vpn.c index 7e6f18dd..4ff98908 100644 --- a/src/libnm-core-impl/nm-setting-vpn.c +++ b/src/libnm-core-impl/nm-setting-vpn.c @@ -148,7 +148,7 @@ nm_setting_vpn_get_user_name(NMSettingVpn *setting) * * Returns: the #NMSettingVpn:persistent property of the setting * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ gboolean nm_setting_vpn_get_persistent(NMSettingVpn *setting) @@ -803,7 +803,7 @@ set_secret_flags(NMSetting *setting, } static GPtrArray * -need_secrets(NMSetting *setting) +need_secrets(NMSetting *setting, gboolean check_rerequest) { /* Assume that VPN connections need secrets since they almost always will */ return g_ptr_array_sized_new(1); @@ -1132,7 +1132,7 @@ nm_setting_vpn_class_init(NMSettingVpnClass *klass) persistent); /** - * NMSettingVpn:data: (type GHashTable(utf8,utf8)): + * NMSettingVpn:data: (type GHashTable(utf8,utf8)) * * Dictionary of key/value pairs of VPN plugin specific data. Both keys and * values must be strings. @@ -1155,7 +1155,7 @@ nm_setting_vpn_class_init(NMSettingVpnClass *klass) &nm_sett_info_propert_type_strdict); /** - * NMSettingVpn:secrets: (type GHashTable(utf8,utf8)): + * NMSettingVpn:secrets: (type GHashTable(utf8,utf8)) * * Dictionary of key/value pairs of VPN plugin specific secrets like * passwords or private keys. Both keys and values must be strings. diff --git a/src/libnm-core-impl/nm-setting-vxlan.c b/src/libnm-core-impl/nm-setting-vxlan.c index f617a073..3fb4c48d 100644 --- a/src/libnm-core-impl/nm-setting-vxlan.c +++ b/src/libnm-core-impl/nm-setting-vxlan.c @@ -344,9 +344,9 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) gboolean remote_is_valid = TRUE; gboolean local_is_valid = TRUE; - if (priv->remote && !nm_utils_parse_inaddr_bin(addr_family, priv->remote, &addr_family, NULL)) + if (priv->remote && !nm_inet_parse_bin(addr_family, priv->remote, &addr_family, NULL)) remote_is_valid = FALSE; - if (priv->local && !nm_utils_parse_inaddr_bin(addr_family, priv->local, &addr_family, NULL)) + if (priv->local && !nm_inet_parse_bin(addr_family, priv->local, &addr_family, NULL)) local_is_valid = FALSE; if (!remote_is_valid) { diff --git a/src/libnm-core-impl/nm-setting-wimax.c b/src/libnm-core-impl/nm-setting-wimax.c index 1e2b51c3..c33ad3ea 100644 --- a/src/libnm-core-impl/nm-setting-wimax.c +++ b/src/libnm-core-impl/nm-setting-wimax.c @@ -178,7 +178,8 @@ nm_setting_wimax_class_init(NMSettingWimaxClass *klass) PROP_NETWORK_NAME, NM_SETTING_PARAM_NONE, NMSettingWimaxPrivate, - network_name); + network_name, + .is_deprecated = TRUE, ); /** * NMSettingWimax:mac-address: @@ -196,7 +197,8 @@ nm_setting_wimax_class_init(NMSettingWimaxClass *klass) NM_SETTING_PARAM_NONE, NMSettingWimaxPrivate, mac_address, - .direct_set_string_mac_address_len = ETH_ALEN); + .direct_set_string_mac_address_len = ETH_ALEN, + .is_deprecated = TRUE, ); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-wired.c b/src/libnm-core-impl/nm-setting-wired.c index 830b2c73..3acd5d97 100644 --- a/src/libnm-core-impl/nm-setting-wired.c +++ b/src/libnm-core-impl/nm-setting-wired.c @@ -292,7 +292,7 @@ nm_setting_wired_get_mac_address_blacklist(NMSettingWired *setting) g_return_val_if_fail(NM_IS_SETTING_WIRED(setting), NULL); priv = NM_SETTING_WIRED_GET_PRIVATE(setting); - return (const char *const *) priv->mac_address_blacklist->data; + return nm_g_array_data(priv->mac_address_blacklist); } /** @@ -327,7 +327,7 @@ nm_setting_wired_get_mac_blacklist_item(NMSettingWired *setting, guint32 idx) priv = NM_SETTING_WIRED_GET_PRIVATE(setting); g_return_val_if_fail(idx <= priv->mac_address_blacklist->len, NULL); - return g_array_index(priv->mac_address_blacklist, const char *, idx); + return nm_g_array_index(priv->mac_address_blacklist, const char *, idx); } /** @@ -355,7 +355,7 @@ nm_setting_wired_add_mac_blacklist_item(NMSettingWired *setting, const char *mac priv = NM_SETTING_WIRED_GET_PRIVATE(setting); for (i = 0; i < priv->mac_address_blacklist->len; i++) { - candidate = g_array_index(priv->mac_address_blacklist, char *, i); + candidate = nm_g_array_index(priv->mac_address_blacklist, char *, i); if (nm_utils_hwaddr_matches(mac, -1, candidate, -1)) return FALSE; } @@ -409,7 +409,7 @@ nm_setting_wired_remove_mac_blacklist_item_by_value(NMSettingWired *setting, con priv = NM_SETTING_WIRED_GET_PRIVATE(setting); for (i = 0; i < priv->mac_address_blacklist->len; i++) { - candidate = g_array_index(priv->mac_address_blacklist, char *, i); + candidate = nm_g_array_index(priv->mac_address_blacklist, char *, i); if (!nm_utils_hwaddr_matches(mac, -1, candidate, -1)) { g_array_remove_index(priv->mac_address_blacklist, i); _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); @@ -810,7 +810,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } for (i = 0; i < priv->mac_address_blacklist->len; i++) { - const char *mac = g_array_index(priv->mac_address_blacklist, const char *, i); + const char *mac = nm_g_array_index(priv->mac_address_blacklist, const char *, i); if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) { g_set_error(error, @@ -1007,7 +1007,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_string(value, nm_setting_wired_get_cloned_mac_address(setting)); break; case PROP_MAC_ADDRESS_BLACKLIST: - g_value_set_boxed(value, (char **) priv->mac_address_blacklist->data); + g_value_set_boxed(value, nm_g_array_data(priv->mac_address_blacklist)); break; case PROP_S390_SUBCHANNELS: g_value_set_boxed(value, priv->s390_subchannels); @@ -1311,7 +1311,8 @@ nm_setting_wired_class_init(NMSettingWiredClass *klass) * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) * (e.g. 0;34;104;18;121;162) * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: mac-address * variable: HWADDR * description: Hardware address of the device in traditional hex-digits-and-colons @@ -1359,13 +1360,15 @@ nm_setting_wired_class_init(NMSettingWiredClass *klass) * (e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete) * (e.g. 0;34;104;18;121;178). * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: cloned-mac-address * variable: MACADDR * description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons * notation (e.g. 00:22:68:14:5A:99). * ---end--- - * ---dbus--- + */ + /* ---dbus--- * property: cloned-mac-address * format: byte array * description: This D-Bus field is deprecated in favor of "assigned-mac-address" @@ -1382,11 +1385,13 @@ nm_setting_wired_class_init(NMSettingWiredClass *klass) _nm_properties_override_gobj( properties_override, obj_properties[PROP_CLONED_MAC_ADDRESS], - NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_BYTESTRING, - .compare_fcn = compare_fcn_cloned_mac_address, - .to_dbus_fcn = _nm_utils_hwaddr_cloned_get, - .from_dbus_fcn = _nm_utils_hwaddr_cloned_set, - .missing_from_dbus_fcn = _nm_utils_hwaddr_cloned_not_set, )); + NM_SETT_INFO_PROPERT_TYPE_DBUS( + G_VARIANT_TYPE_BYTESTRING, + .compare_fcn = compare_fcn_cloned_mac_address, + .to_dbus_fcn = _nm_sett_info_prop_to_dbus_fcn_cloned_mac_address, + .from_dbus_fcn = _nm_sett_info_prop_from_dbus_fcn_cloned_mac_address, + .missing_from_dbus_fcn = _nm_sett_info_prop_missing_from_dbus_fcn_cloned_mac_address, ), + .dbus_deprecated = TRUE); /* ---dbus--- * property: assigned-mac-address @@ -1465,7 +1470,8 @@ nm_setting_wired_class_init(NMSettingWiredClass *klass) * description: MAC address blacklist. * example: mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78 * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: mac-address-blacklist * variable: HWADDR_BLACKLIST(+) * description: It denies usage of the connection for any device whose address @@ -1551,7 +1557,7 @@ nm_setting_wired_class_init(NMSettingWiredClass *klass) s390_nettype); /** - * NMSettingWired:s390-options: (type GHashTable(utf8,utf8)): + * NMSettingWired:s390-options: (type GHashTable(utf8,utf8)) * * Dictionary of key/value pairs of s390-specific device options. Both keys * and values must be strings. Allowed keys include "portno", "layer2", diff --git a/src/libnm-core-impl/nm-setting-wireguard.c b/src/libnm-core-impl/nm-setting-wireguard.c index 599ded3c..a981187f 100644 --- a/src/libnm-core-impl/nm-setting-wireguard.c +++ b/src/libnm-core-impl/nm-setting-wireguard.c @@ -50,7 +50,7 @@ struct _NMWireGuardPeer { char *public_key; char *preshared_key; GPtrArray *allowed_ips; - guint refcount; + int refcount; NMSettingSecretFlags preshared_key_flags; guint16 persistent_keepalive; bool public_key_valid : 1; @@ -127,11 +127,11 @@ nm_wireguard_peer_new_clone(const NMWireGuardPeer *self, gboolean with_secrets) * nm_wireguard_peer_ref: * @self: (allow-none): the #NMWireGuardPeer instance * - * This is not thread-safe. - * * Returns: returns the input argument @self after incrementing * the reference count. * + * Since 1.42, ref-counting of #NMWireGuardPeer is thread-safe. + * * Since: 1.16 */ NMWireGuardPeer * @@ -142,9 +142,9 @@ nm_wireguard_peer_ref(NMWireGuardPeer *self) g_return_val_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE), NULL); - nm_assert(self->refcount < G_MAXUINT); + nm_assert(self->refcount < G_MAXINT); - self->refcount++; + g_atomic_int_inc(&self->refcount); return self; } @@ -155,7 +155,7 @@ nm_wireguard_peer_ref(NMWireGuardPeer *self) * Drop a reference to @self. If the last reference is dropped, * the instance is freed and all associate data released. * - * This is not thread-safe. + * Since 1.42, ref-counting of #NMWireGuardPeer is thread-safe. * * Since: 1.16 */ @@ -167,7 +167,7 @@ nm_wireguard_peer_unref(NMWireGuardPeer *self) g_return_if_fail(NM_IS_WIREGUARD_PEER(self, TRUE)); - if (--self->refcount > 0) + if (!g_atomic_int_dec_and_test(&self->refcount)) return; nm_sock_addr_endpoint_unref(self->endpoint); @@ -628,18 +628,18 @@ _peer_append_allowed_ip(NMWireGuardPeer *self, const char *allowed_ip, gboolean /* normalize the address (if it is valid. Otherwise, take it * as-is (it will render the instance invalid). */ - if (!nm_utils_parse_inaddr_prefix_bin(AF_UNSPEC, allowed_ip, &addr_family, &addrbin, &prefix)) { + if (!nm_inet_parse_with_prefix_bin(AF_UNSPEC, allowed_ip, &addr_family, &addrbin, &prefix)) { if (!accept_invalid) return FALSE; /* mark the entry as invalid by having a "X" prefix. */ str = g_strconcat(ALLOWED_IP_INVALID_X_STR, allowed_ip, NULL); is_valid = FALSE; } else { - char addrstr[NM_UTILS_INET_ADDRSTRLEN]; + char addrstr[NM_INET_ADDRSTRLEN]; nm_assert_addr_family(addr_family); - nm_utils_inet_ntop(addr_family, &addrbin, addrstr); + nm_inet_ntop(addr_family, &addrbin, addrstr); if (prefix >= 0) str = g_strdup_printf("%s/%d", addrstr, prefix); else @@ -1460,7 +1460,7 @@ nm_setting_wireguard_clear_peers(NMSettingWireGuard *self) /*****************************************************************************/ static GVariant * -_peers_dbus_only_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +peers_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { NMSettingWireGuard *self = NM_SETTING_WIREGUARD(setting); NMSettingWireGuardPrivate *priv; @@ -1558,7 +1558,7 @@ _peers_dbus_only_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -_peers_dbus_only_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +peers_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { GVariantIter iter_peers; GVariant *peer_var; @@ -1800,13 +1800,13 @@ verify_secrets(NMSetting *setting, NMConnection *connection, GError **error) } static GPtrArray * -need_secrets(NMSetting *setting) +need_secrets(NMSetting *setting, gboolean check_rerequest) { NMSettingWireGuardPrivate *priv = NM_SETTING_WIREGUARD_GET_PRIVATE(setting); GPtrArray *secrets = NULL; guint i; - if (!priv->private_key_valid) { + if (check_rerequest || !priv->private_key_valid) { secrets = g_ptr_array_new_full(1, g_free); g_ptr_array_add(secrets, g_strdup(NM_SETTING_WIREGUARD_PRIVATE_KEY)); } @@ -1857,9 +1857,7 @@ clear_secrets(const NMSettInfoSetting *sett_info, if (j++ < 5) { /* we use alloca() inside a loop here, but it is guarded to happen at most * a few times. */ - name = peers_psk_get_secret_name_a(/* lgtm [cpp/alloca-in-loop] */ - peer->public_key, - &name_free); + name = peers_psk_get_secret_name_a(peer->public_key, &name_free); } else { name_free = peers_psk_get_secret_name_dup(peer->public_key); name = name_free; @@ -2528,9 +2526,9 @@ nm_setting_wireguard_class_init(NMSettingWireGuardClass *klass) properties_override, NM_SETTING_WIREGUARD_PEERS, NM_SETT_INFO_PROPERT_TYPE_DBUS(NM_G_VARIANT_TYPE("aa{sv}"), - .to_dbus_fcn = _peers_dbus_only_synth, + .to_dbus_fcn = peers_to_dbus, .compare_fcn = compare_fcn_peers, - .from_dbus_fcn = _peers_dbus_only_set, )); + .from_dbus_fcn = peers_from_dbus, )); g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/libnm-core-impl/nm-setting-wireless-security.c b/src/libnm-core-impl/nm-setting-wireless-security.c index ebefd504..a7d12df4 100644 --- a/src/libnm-core-impl/nm-setting-wireless-security.c +++ b/src/libnm-core-impl/nm-setting-wireless-security.c @@ -815,7 +815,7 @@ nm_setting_wireless_security_get_fils(NMSettingWirelessSecurity *setting) } static GPtrArray * -need_secrets(NMSetting *setting) +need_secrets(NMSetting *setting, gboolean check_rerequest) { NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY(setting); NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); @@ -828,22 +828,22 @@ need_secrets(NMSetting *setting) /* Static WEP */ if (strcmp(priv->key_mgmt, "none") == 0) { if ((priv->wep_tx_keyidx == 0) - && !nm_utils_wep_key_valid(priv->wep_key0, priv->wep_key_type)) { + && (check_rerequest || !nm_utils_wep_key_valid(priv->wep_key0, priv->wep_key_type))) { g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0); return secrets; } if ((priv->wep_tx_keyidx == 1) - && !nm_utils_wep_key_valid(priv->wep_key1, priv->wep_key_type)) { + && (check_rerequest || !nm_utils_wep_key_valid(priv->wep_key1, priv->wep_key_type))) { g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1); return secrets; } if ((priv->wep_tx_keyidx == 2) - && !nm_utils_wep_key_valid(priv->wep_key2, priv->wep_key_type)) { + && (check_rerequest || !nm_utils_wep_key_valid(priv->wep_key2, priv->wep_key_type))) { g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2); return secrets; } if ((priv->wep_tx_keyidx == 3) - && !nm_utils_wep_key_valid(priv->wep_key3, priv->wep_key_type)) { + && (check_rerequest || !nm_utils_wep_key_valid(priv->wep_key3, priv->wep_key_type))) { g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3); return secrets; } @@ -852,7 +852,7 @@ need_secrets(NMSetting *setting) /* WPA-PSK infrastructure */ if (strcmp(priv->key_mgmt, "wpa-psk") == 0) { - if (!nm_utils_wpa_psk_valid(priv->psk)) { + if (check_rerequest || !nm_utils_wpa_psk_valid(priv->psk)) { g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_PSK); return secrets; } @@ -861,7 +861,7 @@ need_secrets(NMSetting *setting) /* SAE, used in MESH and WPA3-Personal */ if (strcmp(priv->key_mgmt, "sae") == 0) { - if (!priv->psk || !*priv->psk) { + if (check_rerequest || !priv->psk || !*priv->psk) { g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_PSK); return secrets; } @@ -870,7 +870,7 @@ need_secrets(NMSetting *setting) /* LEAP */ if (priv->auth_alg && !strcmp(priv->auth_alg, "leap") && !strcmp(priv->key_mgmt, "ieee8021x")) { - if (!priv->leap_password || !*priv->leap_password) { + if (check_rerequest || !priv->leap_password || !*priv->leap_password) { g_ptr_array_add(secrets, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD); return secrets; } diff --git a/src/libnm-core-impl/nm-setting-wireless.c b/src/libnm-core-impl/nm-setting-wireless.c index cf391598..33e16d4b 100644 --- a/src/libnm-core-impl/nm-setting-wireless.c +++ b/src/libnm-core-impl/nm-setting-wireless.c @@ -473,7 +473,7 @@ nm_setting_wireless_get_mac_address_blacklist(NMSettingWireless *setting) g_return_val_if_fail(NM_IS_SETTING_WIRELESS(setting), NULL); priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); - return (const char *const *) priv->mac_address_blacklist->data; + return nm_g_array_data(priv->mac_address_blacklist); } /** @@ -508,7 +508,7 @@ nm_setting_wireless_get_mac_blacklist_item(NMSettingWireless *setting, guint32 i priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); g_return_val_if_fail(idx <= priv->mac_address_blacklist->len, NULL); - return g_array_index(priv->mac_address_blacklist, const char *, idx); + return nm_g_array_index(priv->mac_address_blacklist, const char *, idx); } /** @@ -536,7 +536,7 @@ nm_setting_wireless_add_mac_blacklist_item(NMSettingWireless *setting, const cha priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); for (i = 0; i < priv->mac_address_blacklist->len; i++) { - candidate = g_array_index(priv->mac_address_blacklist, char *, i); + candidate = nm_g_array_index(priv->mac_address_blacklist, char *, i); if (nm_utils_hwaddr_matches(mac, -1, candidate, -1)) return FALSE; } @@ -590,7 +590,7 @@ nm_setting_wireless_remove_mac_blacklist_item_by_value(NMSettingWireless *settin priv = NM_SETTING_WIRELESS_GET_PRIVATE(setting); for (i = 0; i < priv->mac_address_blacklist->len; i++) { - candidate = g_array_index(priv->mac_address_blacklist, char *, i); + candidate = nm_g_array_index(priv->mac_address_blacklist, char *, i); if (!nm_utils_hwaddr_matches(mac, -1, candidate, -1)) { g_array_remove_index(priv->mac_address_blacklist, i); _notify(setting, PROP_MAC_ADDRESS_BLACKLIST); @@ -988,7 +988,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } for (i = 0; i < priv->mac_address_blacklist->len; i++) { - const char *mac = g_array_index(priv->mac_address_blacklist, const char *, i); + const char *mac = nm_g_array_index(priv->mac_address_blacklist, const char *, i); if (!nm_utils_hwaddr_valid(mac, ETH_ALEN)) { g_set_error(error, @@ -1123,7 +1123,7 @@ compare_fcn_seen_bssids(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil) /*****************************************************************************/ static GVariant * -nm_setting_wireless_get_security(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +security_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { if (!_nm_connection_serialize_non_secret(flags)) return NULL; @@ -1174,7 +1174,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_string(value, nm_setting_wireless_get_cloned_mac_address(setting)); break; case PROP_MAC_ADDRESS_BLACKLIST: - g_value_set_boxed(value, (char **) priv->mac_address_blacklist->data); + g_value_set_boxed(value, nm_g_array_data(priv->mac_address_blacklist)); break; case PROP_SEEN_BSSIDS: g_value_take_boxed( @@ -1311,7 +1311,8 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) * description: SSID of Wi-Fi network. * example: ssid=Quick Net * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: ssid * variable: ESSID * description: SSID of Wi-Fi network. @@ -1493,7 +1494,8 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) * (e.g. 0;34;104;18;121;162). * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: mac-address * variable: HWADDR * description: Hardware address of the device in traditional hex-digits-and-colons @@ -1540,13 +1542,15 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) * (e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete) * (e.g. 0;34;104;18;121;178). * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: cloned-mac-address * variable: MACADDR * description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons * notation (e.g. 00:22:68:14:5A:99). * ---end--- - * ---dbus--- + */ + /* ---dbus--- * property: cloned-mac-address * format: byte array * description: This D-Bus field is deprecated in favor of "assigned-mac-address" @@ -1563,11 +1567,13 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) _nm_properties_override_gobj( properties_override, obj_properties[PROP_CLONED_MAC_ADDRESS], - NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_BYTESTRING, - .compare_fcn = compare_fcn_cloned_mac_address, - .to_dbus_fcn = _nm_utils_hwaddr_cloned_get, - .from_dbus_fcn = _nm_utils_hwaddr_cloned_set, - .missing_from_dbus_fcn = _nm_utils_hwaddr_cloned_not_set, )); + NM_SETT_INFO_PROPERT_TYPE_DBUS( + G_VARIANT_TYPE_BYTESTRING, + .compare_fcn = compare_fcn_cloned_mac_address, + .to_dbus_fcn = _nm_sett_info_prop_to_dbus_fcn_cloned_mac_address, + .from_dbus_fcn = _nm_sett_info_prop_from_dbus_fcn_cloned_mac_address, + .missing_from_dbus_fcn = _nm_sett_info_prop_missing_from_dbus_fcn_cloned_mac_address, ), + .dbus_deprecated = TRUE, ); /* ---dbus--- * property: assigned-mac-address @@ -1645,7 +1651,8 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) * description: MAC address blacklist. * example: mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78 * ---end--- - * ---ifcfg-rh--- + */ + /* ---ifcfg-rh--- * property: mac-address-blacklist * variable: HWADDR_BLACKLIST(+) * description: It denies usage of the connection for any device whose address @@ -1782,11 +1789,10 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) * the user has set a global default to randomize and the supplicant * supports randomization), %NM_SETTING_MAC_RANDOMIZATION_NEVER (never * randomize the MAC address), or %NM_SETTING_MAC_RANDOMIZATION_ALWAYS - * (always randomize the MAC address). This property is deprecated for - * 'cloned-mac-address'. + * (always randomize the MAC address). * * Since: 1.2 - * Deprecated: 1.4: Deprecated by NMSettingWireless:cloned-mac-address property. + * Deprecated: 1.4: Use the #NMSettingWireless:cloned-mac-address property instead. **/ /* ---ifcfg-rh--- * property: mac-address-randomization @@ -1805,7 +1811,8 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) NM_SETTING_MAC_RANDOMIZATION_DEFAULT, NM_SETTING_PARAM_NONE, NMSettingWirelessPrivate, - mac_address_randomization); + mac_address_randomization, + .is_deprecated = TRUE, ); /* Compatibility for deprecated property */ /* ---ifcfg-rh--- @@ -1813,7 +1820,8 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) * variable: (none) * description: This property is deprecated and not handled by ifcfg-rh-plugin. * ---end--- - * ---dbus--- + */ + /* ---dbus--- * property: security * description: This property is deprecated, but can be set to the value * '802-11-wireless-security' when a wireless security setting is also @@ -1825,8 +1833,9 @@ nm_setting_wireless_class_init(NMSettingWirelessClass *klass) properties_override, "security", NM_SETT_INFO_PROPERT_TYPE_DBUS(G_VARIANT_TYPE_STRING, - .to_dbus_fcn = nm_setting_wireless_get_security, - .compare_fcn = _nm_setting_property_compare_fcn_ignore, )); + .to_dbus_fcn = security_to_dbus, + .compare_fcn = _nm_setting_property_compare_fcn_ignore, ), + .dbus_deprecated = TRUE, ); /** * NMSettingWireless:wake-on-wlan: diff --git a/src/libnm-core-impl/nm-setting-wpan.c b/src/libnm-core-impl/nm-setting-wpan.c index a3e56ded..bc84b01e 100644 --- a/src/libnm-core-impl/nm-setting-wpan.c +++ b/src/libnm-core-impl/nm-setting-wpan.c @@ -77,7 +77,7 @@ G_DEFINE_TYPE(NMSettingWpan, nm_setting_wpan, NM_TYPE_SETTING) * * Returns: the #NMSettingWpan:mac-address property of the setting * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ const char * nm_setting_wpan_get_mac_address(NMSettingWpan *setting) @@ -93,7 +93,7 @@ nm_setting_wpan_get_mac_address(NMSettingWpan *setting) * * Returns: the #NMSettingWpan:pan-id property of the setting * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ guint16 nm_setting_wpan_get_pan_id(NMSettingWpan *setting) @@ -109,7 +109,7 @@ nm_setting_wpan_get_pan_id(NMSettingWpan *setting) * * Returns: the #NMSettingWpan:short-address property of the setting * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ guint16 nm_setting_wpan_get_short_address(NMSettingWpan *setting) @@ -125,7 +125,7 @@ nm_setting_wpan_get_short_address(NMSettingWpan *setting) * * Returns: the #NMSettingWpan:page property of the setting * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ gint16 nm_setting_wpan_get_page(NMSettingWpan *setting) @@ -141,7 +141,7 @@ nm_setting_wpan_get_page(NMSettingWpan *setting) * * Returns: the #NMSettingWpan:channel property of the setting * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ gint16 nm_setting_wpan_get_channel(NMSettingWpan *setting) @@ -213,7 +213,7 @@ nm_setting_wpan_init(NMSettingWpan *setting) * * Returns: (transfer full): the new empty #NMSettingWpan object * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ NMSetting * nm_setting_wpan_new(void) diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c index b6f72137..5a46a1b4 100644 --- a/src/libnm-core-impl/nm-setting.c +++ b/src/libnm-core-impl/nm-setting.c @@ -331,7 +331,7 @@ _nm_setting_class_commit(NMSettingClass *setting_class, override_len = properties_override->len; for (i = 0; i < override_len; i++) { - NMSettInfoProperty *p = &g_array_index(properties_override, NMSettInfoProperty, i); + NMSettInfoProperty *p = &nm_g_array_index(properties_override, NMSettInfoProperty, i); nm_assert((!!p->name) != (!!p->param_spec)); @@ -346,14 +346,14 @@ _nm_setting_class_commit(NMSettingClass *setting_class, #if NM_MORE_ASSERTS > 10 /* assert that properties_override is constructed consistently. */ for (i = 0; i < override_len; i++) { - const NMSettInfoProperty *p = &g_array_index(properties_override, NMSettInfoProperty, i); + const NMSettInfoProperty *p = &nm_g_array_index(properties_override, NMSettInfoProperty, i); gboolean found = FALSE; guint k; - nm_assert( - !_nm_sett_info_property_find_in_array((NMSettInfoProperty *) properties_override->data, - i, - p->name)); + nm_assert(!_nm_sett_info_property_find_in_array( + nm_g_array_index_p(properties_override, NMSettInfoProperty, 0), + i, + p->name)); for (k = 0; k < n_property_specs; k++) { if (!nm_streq(property_specs[k]->name, p->name)) continue; @@ -369,20 +369,20 @@ _nm_setting_class_commit(NMSettingClass *setting_class, const char *name = property_specs[i]->name; NMSettInfoProperty *p; - if (_nm_sett_info_property_find_in_array((NMSettInfoProperty *) properties_override->data, - override_len, - name)) + if (_nm_sett_info_property_find_in_array( + nm_g_array_index_p(properties_override, NMSettInfoProperty, 0), + override_len, + name)) continue; - g_array_set_size(properties_override, properties_override->len + 1); - p = &g_array_index(properties_override, NMSettInfoProperty, properties_override->len - 1); + p = nm_g_array_append_new(properties_override, NMSettInfoProperty); memset(p, 0, sizeof(*p)); p->name = name; p->param_spec = property_specs[i]; } for (i = 0; i < properties_override->len; i++) { - NMSettInfoProperty *p = &g_array_index(properties_override, NMSettInfoProperty, i); + NMSettInfoProperty *p = &nm_g_array_index(properties_override, NMSettInfoProperty, i); GType vtype; if (p->property_type) @@ -492,12 +492,12 @@ _nm_sett_info_setting_get_property_info(const NMSettInfoSetting *sett_info, return NULL; G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMSettInfoProperty, name) == 0); - idx = nm_utils_array_find_binary_search(sett_info->property_infos, - sizeof(NMSettInfoProperty), - sett_info->property_infos_len, - &property_name, - nm_strcmp_p_with_data, - NULL); + idx = nm_array_find_bsearch(sett_info->property_infos, + sett_info->property_infos_len, + sizeof(NMSettInfoProperty), + &property_name, + nm_strcmp_p_with_data, + NULL); if (idx < 0) return NULL; @@ -604,7 +604,48 @@ _nm_setting_use_legacy_property(NMSetting *setting, const char *new_property) { gs_unref_variant GVariant *setting_dict = NULL; - gs_unref_variant GVariant *value = NULL; + gs_unref_variant GVariant *val_leg = NULL; + gs_unref_variant GVariant *val_new = NULL; + + /* We want to be both forward and backward compatible (both the client or the daemon + * can be newer). + * + * For the most part, we achieve that by ignoring unknown properties (to be forward + * compatible). That of course has the downside, that we don't do strong validation + * of the input. + * + * In some cases, we deprecated a D-Bus property for another one (e.g. the legacy property + * "ipv4.routes" became the new property "ipv4.route-data"). In that case, the to/from D-Bus + * methods behave differently on the client and the daemon. + * + * The daemon will serialize both the legacy property and the new property to D-Bus. + * The client, will prefer the newer property (if it exists) when deserializing from D-Bus. + * + * Usually that scheme would fully suffice to support forward and backward compatibility. + * However, there is a problem. An old client (unaware of the new property) might get + * the profile, modify the old property, and send the entire profile back to the daemon. + * In this case, the old client does not know that the new property conflicts with the + * old property. The client also might try to preserve any unknown properties and send + * them back to the daemon. If the daemon now would prefer the new property, it would be wrong. + * + * The solution to this is that the daemon -- when both old and new property is set -- + * will prefer the old property. This is what _nm_setting_use_legacy_property() checks + * for. Consequently, a new client will not serialize both the old and the new property. + * This is done via "to_dbus_only_in_manager_process" flag. + * + * The downside of this scheme is that: + * + * - to/from D-Bus just got more complicated and behaves differently on the client + * and the daemon. + * - backward compatibility does not work with a newer client vs. and older daemon. + * This is the major downside. It's only not that severe, because we only deprecate + * properties seldom and only on major versions. Major version updates happen not + * often and they user might reboot (restart the daemon). + * + * The benefit is that the case with an older client and a newer daemon works, even + * if the client fetches a (new) profile, modifies only parts that it understands, + * and sends back the complete profile (including the new, unmodified properties). + */ if (!connection_dict) { /* we also allow the caller to provide no connection_dict. @@ -626,19 +667,24 @@ _nm_setting_use_legacy_property(NMSetting *setting, g_return_val_if_fail(setting_dict != NULL, FALSE); - /* If the new property isn't set, we have to use the legacy property. */ - value = g_variant_lookup_value(setting_dict, new_property, NULL); - if (!value) - return TRUE; - nm_clear_pointer(&value, g_variant_unref); + if (!_nm_utils_is_manager_process) { + /* The client will prefer the new property, unless it does not exist and + * the legacy property exists. */ + val_new = g_variant_lookup_value(setting_dict, new_property, NULL); + if (!val_new) { + val_leg = g_variant_lookup_value(setting_dict, legacy_property, NULL); + if (val_leg) + return TRUE; + } - /* Otherwise, clients always prefer new properties sent from the daemon. */ - if (!_nm_utils_is_manager_process) return FALSE; + } - /* The daemon prefers the legacy property if it exists. */ - value = g_variant_lookup_value(setting_dict, legacy_property, NULL); - return !!value; + /* The daemon prefers the old property (if it exists). */ + val_leg = g_variant_lookup_value(setting_dict, legacy_property, NULL); + if (val_leg) + return TRUE; + return FALSE; } /*****************************************************************************/ @@ -1256,7 +1302,7 @@ _nm_setting_property_to_dbus_fcn_direct(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_ (const NMValueStrv *) _nm_setting_get_private_field(setting, sett_info, property_info); if (!val->arr) return NULL; - return g_variant_new_strv((const char *const *) val->arr->data, val->arr->len); + return g_variant_new_strv(nm_g_array_data(val->arr), val->arr->len); } default: return nm_assert_unreachable_val(NULL); @@ -1310,7 +1356,7 @@ _nm_setting_property_to_dbus_fcn_gprop(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_n nm_assert(G_VALUE_HOLDS(&prop_value, G_TYPE_ARRAY)); tmp_array = g_value_get_boxed(&prop_value); nm_assert(tmp_array); - return nm_g_variant_new_au((const guint32 *) tmp_array->data, tmp_array->len); + return nm_g_variant_new_au(nm_g_array_data(tmp_array), tmp_array->len); case NM_SETTING_PROPERTY_TO_DBUS_FCN_GPROP_TYPE_STRDICT: nm_assert(G_VALUE_HOLDS(&prop_value, G_TYPE_HASH_TABLE)); return nm_strdict_to_variant_ass(g_value_get_boxed(&prop_value)); @@ -1752,31 +1798,36 @@ property_to_dbus(const NMSettInfoSetting *sett_info, || NM_FLAGS_HAS(property_info->param_spec->flags, G_PARAM_WRITABLE) || property_info->property_type == &nm_sett_info_propert_type_setting_name); - if (property_info->param_spec && !ignore_flags - && !NM_FLAGS_HAS(property_info->param_spec->flags, NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS)) { - if (NM_FLAGS_HAS(property_info->param_spec->flags, NM_SETTING_PARAM_LEGACY) - && !_nm_utils_is_manager_process) + if (ignore_flags) { + /* We are called from _nm_setting_property_compare_fcn_default(). We want + * to serialize the property, and ignore the flags. */ + } else { + if (property_info->to_dbus_only_in_manager_process && !_nm_utils_is_manager_process) return NULL; - if (NM_FLAGS_HAS(property_info->param_spec->flags, NM_SETTING_PARAM_SECRET)) { - NMSettingSecretFlags f = NM_SETTING_SECRET_FLAG_NONE; + if (property_info->param_spec + && !NM_FLAGS_HAS(property_info->param_spec->flags, + NM_SETTING_PARAM_TO_DBUS_IGNORE_FLAGS)) { + if (NM_FLAGS_HAS(property_info->param_spec->flags, NM_SETTING_PARAM_SECRET)) { + NMSettingSecretFlags f = NM_SETTING_SECRET_FLAG_NONE; + + if (NM_FLAGS_ANY(flags, + NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED + | NM_CONNECTION_SERIALIZE_WITH_SECRETS_SYSTEM_OWNED + | NM_CONNECTION_SERIALIZE_WITH_SECRETS_NOT_SAVED)) { + if (!nm_setting_get_secret_flags(setting, + property_info->param_spec->name, + &f, + NULL)) + return NULL; + } - if (NM_FLAGS_ANY(flags, - NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED - | NM_CONNECTION_SERIALIZE_WITH_SECRETS_SYSTEM_OWNED - | NM_CONNECTION_SERIALIZE_WITH_SECRETS_NOT_SAVED)) { - if (!nm_setting_get_secret_flags(setting, - property_info->param_spec->name, - &f, - NULL)) + if (!_nm_connection_serialize_secrets(flags, f)) + return NULL; + } else { + if (!_nm_connection_serialize_non_secret(flags)) return NULL; } - - if (!_nm_connection_serialize_secrets(flags, f)) - return NULL; - } else { - if (!_nm_connection_serialize_non_secret(flags)) - return NULL; } } @@ -3196,6 +3247,12 @@ _nm_setting_clear_secrets(NMSetting *setting, /** * _nm_setting_need_secrets: * @setting: the #NMSetting + * @check_rerequest: If %TRUE: the stored secrets might be wrong and the agent + * should query the user for the correct credentials. If an #NMSetting knows + * that this cannot be the case it should *not* return the corresponding + * setting object. Otherwise it should always return it, even if it is not + * missing. + * If %FALSE: only return it when it is missing. * * Returns an array of property names for each secret which may be required * to make a successful connection. The returned hints are only intended as a @@ -3208,14 +3265,14 @@ _nm_setting_clear_secrets(NMSetting *setting, * free the elements. **/ GPtrArray * -_nm_setting_need_secrets(NMSetting *setting) +_nm_setting_need_secrets(NMSetting *setting, gboolean check_rerequest) { GPtrArray *secrets = NULL; g_return_val_if_fail(NM_IS_SETTING(setting), NULL); if (NM_SETTING_GET_CLASS(setting)->need_secrets) - secrets = NM_SETTING_GET_CLASS(setting)->need_secrets(setting); + secrets = NM_SETTING_GET_CLASS(setting)->need_secrets(setting, check_rerequest); return secrets; } @@ -3513,7 +3570,7 @@ nm_setting_to_string(NMSetting *setting) } static GVariant * -_nm_setting_get_deprecated_virtual_interface_name(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +depreated_interface_name_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { NMSettingConnection *s_con; @@ -3533,8 +3590,9 @@ _nm_setting_get_deprecated_virtual_interface_name(_NM_SETT_INFO_PROP_TO_DBUS_FCN const NMSettInfoPropertType nm_sett_info_propert_type_deprecated_interface_name = NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_STRING, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .to_dbus_fcn = - _nm_setting_get_deprecated_virtual_interface_name, ); + .to_dbus_fcn = depreated_interface_name_to_dbus, + /* from_dbus_fcn() is handled by the connection.interface-name setter. + * See nm_setting_connection_no_interface_name(). */ ); const NMSettInfoPropertType nm_sett_info_propert_type_setting_name = NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_STRING, @@ -4066,6 +4124,233 @@ nm_setting_option_set_uint32(NMSetting *setting, const char *opt_name, guint32 v /*****************************************************************************/ +G_DEFINE_BOXED_TYPE(NMRange, nm_range, nm_range_ref, (GBoxedFreeFunc) nm_range_unref) + +static gboolean +NM_IS_RANGE(const NMRange *self) +{ + return self && self->refcount > 0; +} + +/** + * nm_range_new: + * @start: the first element of the range + * @end: the last element of the range, must be greater than or equal + * to @start. + * + * Creates a new #NMRange object for the given range. Setting @end + * equal to @start creates a single-element range. + * + * Returns: (transfer full): the new #NMRange object. + * + * Since: 1.42 + **/ +NMRange * +nm_range_new(guint64 start, guint64 end) +{ + NMRange *range; + + g_return_val_if_fail(start <= end, NULL); + + range = g_slice_new(NMRange); + *range = (NMRange){ + .refcount = 1, + .start = start, + .end = end, + }; + + return range; +} + +/** + * nm_range_ref: + * @range: the #NMRange + * + * Increases the reference count of the object. + * This is thread-safe. + * + * Returns: the input argument @range object. + * + * Since: 1.42 + **/ +NMRange * +nm_range_ref(const NMRange *range) +{ + g_return_val_if_fail(NM_IS_RANGE(range), NULL); + + nm_assert(range->refcount < G_MAXINT); + + g_atomic_int_inc(&((NMRange *) range)->refcount); + return (NMRange *) range; +} + +/** + * nm_range_unref: + * @range: the #NMRange + * + * Decreases the reference count of the object. If the reference count + * reaches zero the object will be destroyed. + * This is thread-safe. + * + * Since: 1.42 + **/ +void +nm_range_unref(const NMRange *range) +{ + g_return_if_fail(NM_IS_RANGE(range)); + + if (g_atomic_int_dec_and_test(&((NMRange *) range)->refcount)) + nm_g_slice_free((NMRange *) range); +} + +/** + * nm_range_cmp: + * @a: a #NMRange + * @b: another #NMRange + * + * Compare two ranges. + * + * Returns: zero if the two instances are equivalent or + * a non-zero integer otherwise. This defines a total ordering + * over the ranges. + * + * Since: 1.42 + **/ +int +nm_range_cmp(const NMRange *a, const NMRange *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, start); + NM_CMP_FIELD(a, b, end); + + return 0; +} + +/** + * nm_range_get_range: + * @range: the #NMRange + * @start: (out): location to store the start value + * @end: (out): location to store the end value + * + * Gets the start and end values for the range. + * + * Returns: %TRUE if the range contains more than one + * element, %FALSE otherwise. + * + * Since: 1.42 + **/ +gboolean +nm_range_get_range(const NMRange *range, guint64 *start, guint64 *end) +{ + /* with LTO and optimization, the compiler complains that the + * output variables are not initialized. In practice, the function + * only sets the output on success. But make the compiler happy. + */ + NM_SET_OUT(start, 0); + NM_SET_OUT(end, 0); + + g_return_val_if_fail(NM_IS_RANGE(range), 0); + + NM_SET_OUT(start, range->start); + NM_SET_OUT(end, range->end); + + return range->start != range->end; +} + +/** + * nm_range_to_str: + * @range: the %NMRange + * + * Convert a %NMRange to a string. + * + * Returns: (transfer full): a string representing the range. + * + * Since: 1.42 + */ +char * +nm_range_to_str(const NMRange *range) +{ + char buf[200]; + char *b = buf; + gsize l = sizeof(buf); + + g_return_val_if_fail(NM_IS_RANGE(range), NULL); + + nm_strbuf_append(&b, &l, "%" G_GUINT64_FORMAT, range->start); + if (range->start != range->end) + nm_strbuf_append(&b, &l, "-%" G_GUINT64_FORMAT, range->end); + + nm_assert(l > 0); + return nm_memdup_nul(buf, sizeof(buf) - l); +} + +/** + * nm_range_from_str: + * @str: the string representation of a range + * @error: (out) (allow-none): location to store the error on failure + * + * Parses the string representation of the range to create a %NMRange + * instance. + * + * Returns: (transfer full): the %NMRange or %NULL + * + * Since: 1.42 + */ +NMRange * +nm_range_from_str(const char *str, GError **error) +{ + gs_free char *str_free = NULL; + guint64 start; + guint64 end = 0; + char *c; + + g_return_val_if_fail(str, NULL); + g_return_val_if_fail(!error || !*error, NULL); + + c = strchr(str, '-'); + if (c) { + str = nm_strndup_a(300, str, c - str, &str_free); + c++; + } + + start = _nm_utils_ascii_str_to_uint64(str, 10, 0, G_MAXUINT64, 0); + if (errno != 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid range start '%s'", + str); + return NULL; + } + + if (c) { + end = _nm_utils_ascii_str_to_uint64(c, 10, 0, G_MAXUINT64, 0); + if (errno != 0) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid range end '%s'", + c); + return NULL; + } + if (end < start) { + g_set_error(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_FAILED, + "invalid range %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT + ", start must be less than or equal to end", + start, + end); + return NULL; + } + } else + end = start; + + return nm_range_new(start, end); +} + +/*****************************************************************************/ + static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { diff --git a/src/libnm-core-impl/nm-simple-connection.c b/src/libnm-core-impl/nm-simple-connection.c index 6252dc2c..a9c66dc7 100644 --- a/src/libnm-core-impl/nm-simple-connection.c +++ b/src/libnm-core-impl/nm-simple-connection.c @@ -47,9 +47,6 @@ G_DEFINE_TYPE_WITH_CODE(NMSimpleConnection, G_IMPLEMENT_INTERFACE(NM_TYPE_CONNECTION, nm_simple_connection_interface_init);) -#define _GET_PRIVATE(self) \ - G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_SIMPLE_CONNECTION, NMConnectionPrivate) - /*****************************************************************************/ static void @@ -57,7 +54,7 @@ nm_simple_connection_init(NMSimpleConnection *self) { NMConnectionPrivate *priv; - priv = _GET_PRIVATE(self); + priv = _NM_SIMPLE_CONNECTION_GET_CONNECTION_PRIVATE(self); priv->self = (NMConnection *) self; } @@ -139,15 +136,12 @@ NMConnection * nm_simple_connection_new_clone(NMConnection *connection) { NMConnection *clone; - const char *path; g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL); clone = nm_simple_connection_new(); - path = nm_connection_get_path(connection); - if (path) - nm_connection_set_path(clone, path); + _nm_connection_set_path_rstr(clone, _nm_connection_get_path_rstr(connection)); nm_connection_replace_settings_from_connection(clone, connection); @@ -157,14 +151,12 @@ nm_simple_connection_new_clone(NMConnection *connection) static void dispose(GObject *object) { - NMConnection *connection = NM_CONNECTION(object); - #if NM_MORE_ASSERTS g_signal_handlers_disconnect_by_data(object, (gpointer) &_nm_assert_connection_unchanging_user_data); #endif - _nm_connection_private_clear(_GET_PRIVATE(connection)); + _nm_connection_private_clear(_NM_SIMPLE_CONNECTION_GET_CONNECTION_PRIVATE(object)); G_OBJECT_CLASS(nm_simple_connection_parent_class)->dispose(object); } diff --git a/src/libnm-core-impl/nm-team-utils.c b/src/libnm-core-impl/nm-team-utils.c index 6d87f50b..2f62f6c6 100644 --- a/src/libnm-core-impl/nm-team-utils.c +++ b/src/libnm-core-impl/nm-team-utils.c @@ -2148,11 +2148,11 @@ nm_team_setting_config_set(NMTeamSetting *self, const char *js_str) else { gboolean unrecognized_content = FALSE; bool has_lst[_NM_TEAM_ATTRIBUTE_NUM] = { - FALSE, + FALSE, }; NMValueTypUnion val_lst[_NM_TEAM_ATTRIBUTE_NUM]; nm_json_t *found_keys[_NM_TEAM_ATTRIBUTE_NUM] = { - NULL, + NULL, }; gs_unref_ptrarray GPtrArray *ptr_array_master_runner_tx_hash_free = NULL; gs_unref_ptrarray GPtrArray *ptr_array_link_watchers_free = NULL; diff --git a/src/libnm-core-impl/nm-utils-private.h b/src/libnm-core-impl/nm-utils-private.h index 1a6f29ef..e2e1aff7 100644 --- a/src/libnm-core-impl/nm-utils-private.h +++ b/src/libnm-core-impl/nm-utils-private.h @@ -64,11 +64,13 @@ GVariant *_nm_team_settings_property_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS void _nm_team_settings_property_from_dbus_link_watchers( _NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil); -GVariant *_nm_utils_ip4_dns_to_variant(const char *const *dns, gssize len); -GVariant *_nm_utils_ip6_dns_to_variant(const char *const *dns, gssize len); +GVariant *nm_utils_dns_to_variant(int addr_family, const char *const *dns, gssize len); const char *const *nmtst_system_encodings_for_lang(const char *lang); const char *const *nmtst_system_encodings_get_default(void); const char *const *nmtst_system_encodings_get(void); +gboolean +_nm_setting_ovs_verify_connection_type(GType gtype, NMConnection *connection, GError **error); + #endif diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c index 1c6d36c2..8ffc070e 100644 --- a/src/libnm-core-impl/nm-utils.c +++ b/src/libnm-core-impl/nm-utils.c @@ -269,7 +269,7 @@ nm_sock_addr_endpoint_get_fixed_sockaddr(NMSockAddrEndpoint *self, gpointer sock if (!self->host) return FALSE; - if (nm_utils_parse_inaddr_bin(AF_UNSPEC, self->host, &addr_family, &addrbin)) + if (nm_inet_parse_bin(AF_UNSPEC, self->host, &addr_family, &addrbin)) goto good; /* See if there is an IPv6 scope-id... @@ -295,7 +295,7 @@ nm_sock_addr_endpoint_get_fixed_sockaddr(NMSockAddrEndpoint *self, gpointer sock const char *host_part; host_part = nm_strndup_a(200, self->host, s - self->host, &tmp_str); - if (nm_utils_parse_inaddr_bin(AF_INET6, host_part, &addr_family, &addrbin)) + if (nm_inet_parse_bin(AF_INET6, host_part, &addr_family, &addrbin)) goto good; } @@ -1297,12 +1297,30 @@ nm_utils_wpa_psk_valid(const char *psk) GVariant * nm_utils_ip4_dns_to_variant(char **dns) { - return _nm_utils_ip4_dns_to_variant(NM_CAST_STRV_CC(dns), -1); + return nm_utils_dns_to_variant(AF_INET, NM_CAST_STRV_CC(dns), -1); } +/** + * nm_utils_ip6_dns_to_variant: + * @dns: (type utf8): an array of IP address strings + * + * Utility function to convert an array of IP address strings int a #GVariant of + * type 'aay' representing an array of IPv6 addresses. + * + * If a string cannot be parsed, it will be silently ignored. + * + * Returns: (transfer none): a new floating #GVariant representing @dns. + **/ GVariant * -_nm_utils_ip4_dns_to_variant(const char *const *dns, gssize len) +nm_utils_ip6_dns_to_variant(char **dns) { + return nm_utils_dns_to_variant(AF_INET6, NM_CAST_STRV_CC(dns), -1); +} + +GVariant * +nm_utils_dns_to_variant(int addr_family, const char *const *dns, gssize len) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); GVariantBuilder builder; gsize l; gsize i; @@ -1312,13 +1330,20 @@ _nm_utils_ip4_dns_to_variant(const char *const *dns, gssize len) else l = len; - g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); + g_variant_builder_init(&builder, IS_IPv4 ? G_VARIANT_TYPE("au") : G_VARIANT_TYPE("aay")); for (i = 0; i < l; i++) { - in_addr_t ip; + NMIPAddr ip; + + /* We can only represent the IP address on the legacy property "ipv[46].dns". + * Expose what we can. */ + if (!nm_utils_dnsname_parse(addr_family, dns[i], NULL, &ip, NULL)) + continue; - if (inet_pton(AF_INET, dns[i], &ip) == 1) + if (IS_IPv4) g_variant_builder_add(&builder, "u", ip); + else + g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&ip.addr6)); } return g_variant_builder_end(&builder); @@ -1346,7 +1371,7 @@ nm_utils_ip4_dns_from_variant(GVariant *value) array = g_variant_get_fixed_array(value, &length, sizeof(guint32)); dns = g_new(char *, length + 1u); for (i = 0; i < length; i++) - dns[i] = nm_utils_inet4_ntop_dup(array[i]); + dns[i] = nm_inet4_ntop_dup(array[i]); dns[i] = NULL; return dns; @@ -1449,7 +1474,7 @@ nm_utils_ip4_addresses_from_variant(GVariant *value, char **out_gateway) g_ptr_array_add(addresses, addr); if (addr_array[2] && out_gateway && !*out_gateway) - *out_gateway = nm_utils_inet4_ntop_dup(addr_array[2]); + *out_gateway = nm_inet4_ntop_dup(addr_array[2]); } else { g_warning("Ignoring invalid IP4 address: %s", error->message); g_clear_error(&error); @@ -1571,7 +1596,7 @@ nm_utils_ip4_routes_from_variant(GVariant *value) guint32 nm_utils_ip4_netmask_to_prefix(guint32 netmask) { - return _nm_utils_ip4_netmask_to_prefix(netmask); + return nm_ip4_addr_netmask_to_prefix(netmask); } /** @@ -1585,7 +1610,7 @@ nm_utils_ip4_prefix_to_netmask(guint32 prefix) { g_return_val_if_fail(prefix <= 32, 0xffffffffu); - return _nm_utils_ip4_prefix_to_netmask(prefix); + return nm_ip4_addr_netmask_from_prefix(prefix); } /** @@ -1603,47 +1628,7 @@ nm_utils_ip4_prefix_to_netmask(guint32 prefix) guint32 nm_utils_ip4_get_default_prefix(guint32 ip) { - return _nm_utils_ip4_get_default_prefix(ip); -} - -/** - * nm_utils_ip6_dns_to_variant: - * @dns: (type utf8): an array of IP address strings - * - * Utility function to convert an array of IP address strings int a #GVariant of - * type 'aay' representing an array of IPv6 addresses. - * - * If a string cannot be parsed, it will be silently ignored. - * - * Returns: (transfer none): a new floating #GVariant representing @dns. - **/ -GVariant * -nm_utils_ip6_dns_to_variant(char **dns) -{ - return _nm_utils_ip6_dns_to_variant(NM_CAST_STRV_CC(dns), -1); -} - -GVariant * -_nm_utils_ip6_dns_to_variant(const char *const *dns, gssize len) -{ - GVariantBuilder builder; - gsize i; - gsize l; - - if (len < 0) - l = NM_PTRARRAY_LEN(dns); - else - l = len; - - g_variant_builder_init(&builder, G_VARIANT_TYPE("aay")); - for (i = 0; i < l; i++) { - struct in6_addr ip; - - if (inet_pton(AF_INET6, dns[i], &ip) != 1) - continue; - g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(&ip)); - } - return g_variant_builder_end(&builder); + return nm_ip4_addr_get_default_prefix(ip); } /** @@ -1676,7 +1661,7 @@ nm_utils_ip6_dns_from_variant(GVariant *value) const struct in6_addr *ip = g_variant_get_fixed_array(ip_var, &length, 1); if (length == sizeof(struct in6_addr)) - dns[i++] = nm_utils_inet6_ntop_dup(ip); + dns[i++] = nm_inet6_ntop_dup(ip); g_variant_unref(ip_var); } @@ -1798,7 +1783,7 @@ nm_utils_ip6_addresses_from_variant(GVariant *value, char **out_gateway) goto next; } if (!IN6_IS_ADDR_UNSPECIFIED(gateway_bytes)) - *out_gateway = nm_utils_inet6_ntop_dup(gateway_bytes); + *out_gateway = nm_inet6_ntop_dup(gateway_bytes); } } else { g_warning("Ignoring invalid IP6 address: %s", error->message); @@ -1943,7 +1928,7 @@ next: * * Returns: (transfer none): a new floating #GVariant representing @addresses. * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ GVariant * nm_utils_ip_addresses_to_variant(GPtrArray *addresses) @@ -1998,7 +1983,7 @@ nm_utils_ip_addresses_to_variant(GPtrArray *addresses) * Returns: (transfer full) (element-type NMIPAddress): a newly allocated * #GPtrArray of #NMIPAddress objects * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ GPtrArray * nm_utils_ip_addresses_from_variant(GVariant *value, int family) @@ -2059,7 +2044,7 @@ nm_utils_ip_addresses_from_variant(GVariant *value, int family) * * Returns: (transfer none): a new floating #GVariant representing @routes. * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ GVariant * nm_utils_ip_routes_to_variant(GPtrArray *routes) @@ -2127,7 +2112,7 @@ nm_utils_ip_routes_to_variant(GPtrArray *routes) * Returns: (transfer full) (element-type NMIPRoute): a newly allocated * #GPtrArray of #NMIPRoute objects * - * Since: 1.42, 1.40.4 + * Since: 1.42 **/ GPtrArray * nm_utils_ip_routes_from_variant(GVariant *value, int family) @@ -3833,13 +3818,13 @@ _nm_utils_ipaddr_canonical_or_invalid(int addr_family, const char *ip, gboolean if (!ip) return NULL; - if (!nm_utils_parse_inaddr_bin(addr_family, ip, &addr_family, &addr_bin)) + if (!nm_inet_parse_bin(addr_family, ip, &addr_family, &addr_bin)) return g_strdup(ip); if (map_zero_to_null && nm_ip_addr_is_null(addr_family, &addr_bin)) return NULL; - return nm_utils_inet_ntop_dup(addr_family, &addr_bin); + return nm_inet_ntop_dup(addr_family, &addr_bin); } /* @@ -3988,7 +3973,7 @@ nm_utils_hwaddr_to_dbus(const char *str) } GVariant * -_nm_utils_hwaddr_cloned_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +_nm_sett_info_prop_to_dbus_fcn_cloned_mac_address(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_free char *addr = NULL; @@ -3999,7 +3984,7 @@ _nm_utils_hwaddr_cloned_get(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } gboolean -_nm_utils_hwaddr_cloned_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +_nm_sett_info_prop_from_dbus_fcn_cloned_mac_address(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { gsize length; const guint8 *array; @@ -4030,14 +4015,15 @@ _nm_utils_hwaddr_cloned_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) } gboolean -_nm_utils_hwaddr_cloned_not_set(_NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil) +_nm_sett_info_prop_missing_from_dbus_fcn_cloned_mac_address( + _NM_SETT_INFO_PROP_MISSING_FROM_DBUS_FCN_ARGS _nm_nil) { nm_assert(nm_streq0(property, "cloned-mac-address")); return TRUE; } static GVariant * -_nm_utils_hwaddr_cloned_data_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +assigned_mac_address_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) { gs_free char *addr = NULL; @@ -4066,7 +4052,7 @@ _nm_utils_hwaddr_cloned_data_synth(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) } static gboolean -_nm_utils_hwaddr_cloned_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +assigned_mac_address_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { nm_assert(nm_streq0(property_info->name, "assigned-mac-address")); @@ -4088,8 +4074,8 @@ _nm_utils_hwaddr_cloned_data_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) const NMSettInfoPropertType nm_sett_info_propert_type_assigned_mac_address = NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_STRING, .compare_fcn = _nm_setting_property_compare_fcn_ignore, - .to_dbus_fcn = _nm_utils_hwaddr_cloned_data_synth, - .from_dbus_fcn = _nm_utils_hwaddr_cloned_data_set, ); + .to_dbus_fcn = assigned_mac_address_to_dbus, + .from_dbus_fcn = assigned_mac_address_from_dbus, ); /*****************************************************************************/ @@ -4255,13 +4241,13 @@ _nm_utils_generate_mac_address_mask_parse(const char *value, ouis = g_array_sized_new(FALSE, FALSE, sizeof(struct ether_addr), 4); do { + struct ether_addr *new; + s = s_next; s_next = _split_word(s); - g_array_set_size(ouis, ouis->len + 1); - if (!nm_utils_hwaddr_aton(s, - &g_array_index(ouis, struct ether_addr, ouis->len - 1), - ETH_ALEN)) { + new = nm_g_array_append_new(ouis, struct ether_addr); + if (!nm_utils_hwaddr_aton(s, new, ETH_ALEN)) { g_set_error(error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, @@ -4373,13 +4359,13 @@ nm_utils_is_uuid(const char *str) return nm_uuid_is_valid_nmlegacy(str); } -static _nm_thread_local char _nm_utils_inet_ntop_buffer[NM_UTILS_INET_ADDRSTRLEN]; +static _nm_thread_local char _nm_utils_inet_ntop_buffer[NM_INET_ADDRSTRLEN]; /** * nm_utils_inet4_ntop: (skip) * @inaddr: the address that should be converted to string. * @dst: the destination buffer, it must contain at least - * <literal>INET_ADDRSTRLEN</literal> or %NM_UTILS_INET_ADDRSTRLEN + * <literal>INET_ADDRSTRLEN</literal> or %NM_INET_ADDRSTRLEN * characters. If set to %NULL, it will return a pointer to an internal, static * buffer (shared with nm_utils_inet6_ntop()). Beware, that the internal * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or @@ -4401,14 +4387,14 @@ nm_utils_inet4_ntop(in_addr_t inaddr, char *dst) * * However, still support it to be lenient against mistakes and because * this is public API of libnm. */ - return _nm_utils_inet4_ntop(inaddr, dst ?: _nm_utils_inet_ntop_buffer); + return nm_inet4_ntop(inaddr, dst ?: _nm_utils_inet_ntop_buffer); } /** * nm_utils_inet6_ntop: (skip) * @in6addr: the address that should be converted to string. * @dst: the destination buffer, it must contain at least - * <literal>INET6_ADDRSTRLEN</literal> or %NM_UTILS_INET_ADDRSTRLEN + * <literal>INET6_ADDRSTRLEN</literal> or %NM_INET_ADDRSTRLEN * characters. If set to %NULL, it will return a pointer to an internal, static * buffer (shared with nm_utils_inet4_ntop()). Beware, that the internal * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or @@ -4432,7 +4418,7 @@ nm_utils_inet6_ntop(const struct in6_addr *in6addr, char *dst) * However, still support it to be lenient against mistakes and because * this is public API of libnm. */ g_return_val_if_fail(in6addr, NULL); - return _nm_utils_inet6_ntop(in6addr, dst ?: _nm_utils_inet_ntop_buffer); + return nm_inet6_ntop(in6addr, dst ?: _nm_utils_inet_ntop_buffer); } /** @@ -4450,7 +4436,7 @@ nm_utils_ipaddr_valid(int family, const char *ip) { g_return_val_if_fail(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC, FALSE); - return nm_utils_ipaddr_is_valid(family, ip); + return nm_inet_is_valid(family, ip); } /** @@ -5030,11 +5016,8 @@ _nm_variant_attribute_spec_find_binary_search(const NMVariantAttributeSpec *cons G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMVariantAttributeSpec, name) == 0); - idx = nm_utils_ptrarray_find_binary_search((gconstpointer *) array, - len, - &name, - nm_strcmp_p_with_data, - NULL); + idx = + nm_ptrarray_find_bsearch((gconstpointer *) array, len, &name, nm_strcmp_p_with_data, NULL); if (idx < 0) return NULL; return array[idx]; @@ -5589,6 +5572,97 @@ _nm_utils_bridge_vlan_verify_list(GPtrArray *vlans, return TRUE; } +GVariant * +_nm_utils_ranges_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil) +{ + gs_unref_ptrarray GPtrArray *ranges = NULL; + GVariantBuilder builder; + const char *property_name = property_info->name; + guint i; + + nm_assert(property_name); + + g_object_get(setting, property_name, &ranges, NULL); + g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); + + if (ranges) { + for (i = 0; i < ranges->len; i++) { + NMRange *range = ranges->pdata[i]; + GVariantBuilder range_builder; + + g_variant_builder_init(&range_builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&range_builder, + "{sv}", + "start", + g_variant_new_uint64(range->start)); + g_variant_builder_add(&range_builder, "{sv}", "end", g_variant_new_uint64(range->end)); + + g_variant_builder_add(&builder, "a{sv}", &range_builder); + } + } + + return g_variant_builder_end(&builder); +} + +gboolean +_nm_utils_ranges_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) +{ + gs_unref_ptrarray GPtrArray *ranges = NULL; + GVariantIter iter; + GVariant *range_var; + + g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), FALSE); + + ranges = g_ptr_array_new_with_free_func((GDestroyNotify) nm_range_unref); + g_variant_iter_init(&iter, value); + while (g_variant_iter_next(&iter, "@a{sv}", &range_var)) { + _nm_unused gs_unref_variant GVariant *var_unref = range_var; + gint64 start; + gint64 end; + + if (!g_variant_lookup(range_var, "start", "t", &start)) + continue; + if (!g_variant_lookup(range_var, "end", "t", &end)) + continue; + if (start > end) + continue; + + g_ptr_array_add(ranges, nm_range_new(start, end)); + } + + g_object_set(setting, property_info->name, ranges, NULL); + + return TRUE; +} + +NMTernary +_nm_utils_ranges_cmp(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_nil) +{ + const GPtrArray *ranges_a = NULL; + const GPtrArray *ranges_b = NULL; + guint len; + guint i; + + if (nm_streq0(nm_setting_get_name(set_a), NM_SETTING_OVS_PORT_SETTING_NAME) + && nm_streq0(property_info->name, NM_SETTING_OVS_PORT_TRUNKS)) { + ranges_a = _nm_setting_ovs_port_get_trunks_arr(NM_SETTING_OVS_PORT(set_a)); + if (set_b) + ranges_b = _nm_setting_ovs_port_get_trunks_arr(NM_SETTING_OVS_PORT(set_b)); + } else { + nm_assert_not_reached(); + } + + len = nm_g_ptr_array_len(ranges_a); + if (len != nm_g_ptr_array_len(ranges_b)) + return FALSE; + for (i = 0; i < len; i++) { + if (nm_range_cmp(ranges_a->pdata[i], ranges_b->pdata[i])) + return FALSE; + } + + return TRUE; +} + gboolean _nm_utils_iaid_verify(const char *str, gint64 *out_value) { @@ -5660,3 +5734,24 @@ _nm_utils_validate_dhcp_hostname_flags(NMDhcpHostnameFlags flags, int addr_famil return TRUE; } + +/*****************************************************************************/ + +/** + * nm_utils_ensure_gtypes: + * + * This ensures that all NMSetting GTypes are created. For example, + * after this call, g_type_from_name("NMSettingConnection") will work. + * + * This cannot fail and does nothing if the type already exists. + * + * Since: 1.42 + */ +void +nm_utils_ensure_gtypes(void) +{ + NMMetaSettingType meta_type; + + for (meta_type = 0; meta_type < _NM_META_SETTING_TYPE_NUM; meta_type++) + nm_meta_setting_infos[meta_type].get_setting_gtype(); +} diff --git a/src/libnm-core-impl/nm-vpn-plugin-info.c b/src/libnm-core-impl/nm-vpn-plugin-info.c index baa19347..61e9cde5 100644 --- a/src/libnm-core-impl/nm-vpn-plugin-info.c +++ b/src/libnm-core-impl/nm-vpn-plugin-info.c @@ -198,7 +198,7 @@ _sort_files(LoadDirInfo *a, LoadDirInfo *b) * VPN plugin directory. */ const char * -_nm_vpn_plugin_info_get_default_dir_etc() +_nm_vpn_plugin_info_get_default_dir_etc(void) { return DEFAULT_DIR_ETC; } @@ -210,7 +210,7 @@ _nm_vpn_plugin_info_get_default_dir_etc() * VPN plugin directory. */ const char * -_nm_vpn_plugin_info_get_default_dir_lib() +_nm_vpn_plugin_info_get_default_dir_lib(void) { return DEFAULT_DIR_LIB; } @@ -223,7 +223,7 @@ _nm_vpn_plugin_info_get_default_dir_lib() * that directory. */ const char * -_nm_vpn_plugin_info_get_default_dir_user() +_nm_vpn_plugin_info_get_default_dir_user(void) { return nm_str_not_empty(g_getenv("NM_VPN_PLUGIN_DIR")); } @@ -296,7 +296,7 @@ _nm_vpn_plugin_info_list_load_dir(const char *dirname, g_array_sort(array, (GCompareFunc) _sort_files); for (i = 0; i < array->len; i++) - res = g_slist_prepend(res, g_array_index(array, LoadDirInfo, i).plugin_info); + res = g_slist_prepend(res, nm_g_array_index(array, LoadDirInfo, i).plugin_info); g_array_unref(array); @@ -312,7 +312,7 @@ _nm_vpn_plugin_info_list_load_dir(const char *dirname, * Since: 1.2 */ GSList * -nm_vpn_plugin_info_list_load() +nm_vpn_plugin_info_list_load(void) { int i; gint64 uid; @@ -898,7 +898,7 @@ nm_vpn_plugin_info_get_program(NMVpnPluginInfo *self) * * Returns: %TRUE if the service supports multiple instances with different bus names, otherwise %FALSE * - * Since: 1.42, 1.40.4 + * Since: 1.42 */ gboolean nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self) diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c index a21f50db..f6684bfb 100644 --- a/src/libnm-core-impl/tests/test-general.c +++ b/src/libnm-core-impl/tests/test-general.c @@ -2501,6 +2501,9 @@ test_setting_ip_route_attributes(void) TEST_ATTR("tos", byte, 127, AF_INET, TRUE, TRUE); TEST_ATTR("tos", string, "0x28", AF_INET, FALSE, TRUE); + TEST_ATTR("weight", uint32, 100, AF_INET, TRUE, TRUE); + TEST_ATTR("weight", string, "100", AF_INET, FALSE, TRUE); + TEST_ATTR("advmss", uint32, 1400, AF_INET, TRUE, TRUE); TEST_ATTR("advmss", string, "1400", AF_INET, FALSE, TRUE); @@ -3900,7 +3903,7 @@ ensure_diffs(GHashTable *diffs, const DiffSetting *check, gsize n_check) { guint i; - g_assert(g_hash_table_size(diffs) == n_check); + g_assert_cmpint(g_hash_table_size(diffs), ==, n_check); /* Loop through the settings */ for (i = 0; i < n_check; i++) { @@ -3913,14 +3916,14 @@ ensure_diffs(GHashTable *diffs, const DiffSetting *check, gsize n_check) /* Get the number of keys to check */ while (check[i].keys[z].key_name) z++; - g_assert(g_hash_table_size(setting_hash) == z); + g_assert_cmpint(g_hash_table_size(setting_hash), ==, z); /* Now compare the actual keys */ for (z = 0; check[i].keys[z].key_name; z++) { NMSettingDiffResult result; result = GPOINTER_TO_UINT(g_hash_table_lookup(setting_hash, check[i].keys[z].key_name)); - g_assert(result == check[i].keys[z].result); + g_assert_cmpint(result, ==, check[i].keys[z].result); } } } @@ -4010,6 +4013,7 @@ test_connection_diff_a_only(void) {NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER, NM_SETTING_DIFF_RESULT_IN_A}, {NM_SETTING_IP_CONFIG_DHCP_REJECT_SERVERS, NM_SETTING_DIFF_RESULT_IN_A}, {NM_SETTING_IP4_CONFIG_LINK_LOCAL, NM_SETTING_DIFF_RESULT_IN_A}, + {NM_SETTING_IP_CONFIG_AUTO_ROUTE_EXT_GW, NM_SETTING_DIFF_RESULT_IN_A}, {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, }}, }; @@ -4052,11 +4056,11 @@ test_connection_diff_different(void) NMSettingIPConfig *s_ip4; gboolean same; const DiffSetting settings[] = { - {NM_SETTING_IP4_CONFIG_SETTING_NAME, + {NM_SETTING_IP4_CONFIG_SETTING_NAME, { - {NM_SETTING_IP_CONFIG_METHOD, + {NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B}, - {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, + {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, }}, }; @@ -4137,10 +4141,10 @@ test_connection_diff_inferrable(void) NMSettingIPConfig *s_ip4; char *uuid; const DiffSetting settings[] = { - {NM_SETTING_CONNECTION_SETTING_NAME, + {NM_SETTING_CONNECTION_SETTING_NAME, { - {NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A}, - {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, + {NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A}, + {NULL, NM_SETTING_DIFF_RESULT_UNKNOWN}, }}, }; @@ -5061,7 +5065,7 @@ _netmask_to_prefix(guint32 netmask) /* we re-implemented the netmask-to-prefix code differently. Check * that they agree. */ - g_assert_cmpint(prefix, ==, _nm_utils_ip4_netmask_to_prefix(netmask)); + g_assert_cmpint(prefix, ==, nm_ip4_addr_netmask_to_prefix(netmask)); return prefix; } @@ -5072,7 +5076,7 @@ test_ip4_prefix_to_netmask(void) int i; for (i = 0; i <= 32; i++) { - guint32 netmask = _nm_utils_ip4_prefix_to_netmask(i); + guint32 netmask = nm_ip4_addr_netmask_from_prefix(i); int plen = _netmask_to_prefix(netmask); g_assert_cmpint(i, ==, plen); @@ -5100,8 +5104,8 @@ test_ip4_netmask_to_prefix(void) g_rand_set_seed(rand, 1); for (i = 2; i <= 32; i++) { - guint32 netmask = _nm_utils_ip4_prefix_to_netmask(i); - guint32 netmask_lowest_bit = netmask & ~_nm_utils_ip4_prefix_to_netmask(i - 1); + guint32 netmask = nm_ip4_addr_netmask_from_prefix(i); + guint32 netmask_lowest_bit = netmask & ~nm_ip4_addr_netmask_from_prefix(i - 1); g_assert_cmpint(i, ==, _netmask_to_prefix(netmask)); @@ -5250,7 +5254,8 @@ test_setting_ip4_changed_signal(void) ASSERT_CHANGED(nm_setting_ip_config_add_dns(s_ip4, "11.22.0.0")); ASSERT_CHANGED(nm_setting_ip_config_remove_dns(s_ip4, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns->len)); + NMTST_EXPECT_LIBNM_CRITICAL( + NMTST_G_RETURN_MSG(idx >= 0 && ((guint) idx) < nm_g_ptr_array_len(priv->dns))); ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns(s_ip4, 1)); g_test_assert_expected_messages(); @@ -5326,7 +5331,8 @@ test_setting_ip6_changed_signal(void) ASSERT_CHANGED(nm_setting_ip_config_add_dns(s_ip6, "1:2:3::4:5:6")); ASSERT_CHANGED(nm_setting_ip_config_remove_dns(s_ip6, 0)); - NMTST_EXPECT_LIBNM_CRITICAL(NMTST_G_RETURN_MSG(idx >= 0 && idx < priv->dns->len)); + NMTST_EXPECT_LIBNM_CRITICAL( + NMTST_G_RETURN_MSG(idx >= 0 && ((guint) idx) < nm_g_ptr_array_len(priv->dns))); ASSERT_UNCHANGED(nm_setting_ip_config_remove_dns(s_ip6, 1)); g_test_assert_expected_messages(); @@ -6957,7 +6963,7 @@ test_setting_ip6_gateway(void) gateway_bytes = g_variant_get_fixed_array(gateway_var, &length, 1); g_assert_cmpint(length, ==, 16); - nmtst_assert_ip6_address((struct in6_addr *) gateway_bytes, "abcd::1"); + nmtst_assert_ip6_address(NM_CAST_ALIGN(struct in6_addr, gateway_bytes), "abcd::1"); g_variant_unref(gateway_var); } g_variant_unref(value); @@ -7143,7 +7149,7 @@ _sock_addr_endpoint_fixed(const char *endpoint, const char *host, guint16 port, g_assert(host); g_assert(port > 0); - if (!nm_utils_parse_inaddr_bin(AF_UNSPEC, host, &addr_family, &addrbin)) + if (!nm_inet_parse_bin(AF_UNSPEC, host, &addr_family, &addrbin)) g_assert_not_reached(); ep = nm_sock_addr_endpoint_new(endpoint); @@ -7887,13 +7893,13 @@ test_nm_utils_uuid_generate_from_string(void) NM_UUID_NS_DNS); for (i = 0; i < G_N_ELEMENTS(zero_uuids); i++) { - nm_sprintf_buf(i_str, "%u", i), - _test_uuid(NM_UUID_TYPE_VERSION3, zero_uuids[i].uuid3, i_str, -1, NULL); + nm_sprintf_buf(i_str, "%u", i); + _test_uuid(NM_UUID_TYPE_VERSION3, zero_uuids[i].uuid3, i_str, -1, NULL); _test_uuid(NM_UUID_TYPE_VERSION5, zero_uuids[i].uuid5, i_str, -1, NULL); } for (i = 0; i < G_N_ELEMENTS(dns_uuids); i++) { - nm_sprintf_buf(i_str, "%u", i), - _test_uuid(NM_UUID_TYPE_VERSION3, dns_uuids[i].uuid3, i_str, -1, NM_UUID_NS_DNS); + nm_sprintf_buf(i_str, "%u", i); + _test_uuid(NM_UUID_TYPE_VERSION3, dns_uuids[i].uuid3, i_str, -1, NM_UUID_NS_DNS); _test_uuid(NM_UUID_TYPE_VERSION5, dns_uuids[i].uuid5, i_str, -1, NM_UUID_NS_DNS); } @@ -7949,12 +7955,52 @@ test_nm_utils_uuid_generate_from_string(void) /*****************************************************************************/ static void -__test_uuid(const char *expected_uuid, const char *str, gssize slen, char *uuid_test) +_check_uuid(NMUuidType uuid_type, + const NMUuid *type_arg, + const char *expected_uuid, + const char *str, + gssize slen, + const char *const *strv, + gssize strv_len) { + gs_free char *uuid_test = NULL; + gs_free char *uuid_test2 = NULL; + gboolean uuid_test2_valid = TRUE; + + g_assert(str); + g_assert(strv_len < 0 || strv); + + uuid_test = nm_uuid_generate_from_strings_strv(uuid_type, type_arg, strv, strv_len); + g_assert(uuid_test); g_assert(nm_uuid_is_normalized(uuid_test)); - if (strcmp(uuid_test, expected_uuid)) { + if (strv_len < 0 && strv) { + uuid_test2 = + nm_uuid_generate_from_strings_strv(uuid_type, type_arg, strv, NM_PTRARRAY_LEN(strv)); + } else if (strv_len >= 0) { + gssize l = nm_strv_find_first(strv, strv_len, NULL); + gs_free const char **strv2 = nm_strv_dup_packed(strv, l < 0 ? strv_len : l); + + uuid_test2 = nm_uuid_generate_from_strings_strv(uuid_type, + type_arg, + strv2 ?: NM_STRV_EMPTY_CC(), + -1); + if (l >= 0) { + /* there are NULL strings. The result won't be match. */ + uuid_test2_valid = FALSE; + } + } + if (uuid_test2) { + if (uuid_test2_valid) + g_assert_cmpstr(uuid_test, ==, uuid_test2); + else { + g_assert(nm_uuid_is_normalized(uuid_test)); + g_assert_cmpstr(uuid_test, !=, uuid_test2); + } + } + + if (!nm_streq(uuid_test, expected_uuid)) { g_error("UUID test failed (1): text=%s, len=%lld, expected=%s, uuid_test=%s", str, (long long) slen, @@ -7963,7 +8009,7 @@ __test_uuid(const char *expected_uuid, const char *str, gssize slen, char *uuid_ } g_free(uuid_test); - uuid_test = nm_uuid_generate_from_string_str(str, slen, NM_UUID_TYPE_VERSION3, &nm_uuid_ns_1); + uuid_test = nm_uuid_generate_from_string_str(str, slen, uuid_type, type_arg); g_assert(uuid_test); g_assert(nm_utils_is_uuid(uuid_test)); @@ -7975,11 +8021,20 @@ __test_uuid(const char *expected_uuid, const char *str, gssize slen, char *uuid_ expected_uuid, uuid_test); } - g_free(uuid_test); } -#define _test_uuid(expected_uuid, str, strlen, ...) \ - __test_uuid(expected_uuid, str, strlen, nm_uuid_generate_from_strings(__VA_ARGS__, NULL)) +#define check_uuid(uuid_type, type_arg, expected_uuid, str, ...) \ + ({ \ + const NMUuidType _uuid_type = (uuid_type); \ + const NMUuid *_type_arg = type_arg; \ + const char *_expected_uuid = (expected_uuid); \ + const char *_str = (str); \ + const gsize _strlen = NM_STRLEN(str); \ + const char *const *_strv = NM_MAKE_STRV(__VA_ARGS__); \ + const gssize _strv_len = NM_NARG(__VA_ARGS__); \ + \ + _check_uuid(_uuid_type, _type_arg, _expected_uuid, _str, _strlen, _strv, _strv_len); \ + }) static void test_nm_utils_uuid_generate_from_strings(void) @@ -8001,20 +8056,157 @@ test_nm_utils_uuid_generate_from_strings(void) g_assert_cmpstr(NM_UUID_NS_1, ==, nm_uuid_unparse(&nm_uuid_ns_1, buf)); g_assert_cmpstr(NM_UUID_NS_ZERO, ==, nm_uuid_unparse(&nm_uuid_ns_zero, buf)); - _test_uuid("b07c334a-399b-32de-8d50-58e4e08f98e3", "", 0, NULL); - _test_uuid("b8a426cb-bcb5-30a3-bd8f-6786fea72df9", "\0", 1, ""); - _test_uuid("12a4a982-7aae-39e1-951e-41aeb1250959", "a\0", 2, "a"); - _test_uuid("69e22c7e-f89f-3a43-b239-1cb52ed8db69", "aa\0", 3, "aa"); - _test_uuid("59829fd3-5ad5-3d90-a7b0-4911747e4088", "\0\0", 2, "", ""); - _test_uuid("01ad0e06-6c50-3384-8d86-ddab81421425", "a\0\0", 3, "a", ""); - _test_uuid("e1ed8647-9ed3-3ec8-8c6d-e8204524d71d", "aa\0\0", 4, "aa", ""); - _test_uuid("fb1c7cd6-275c-3489-9382-83b900da8af0", "\0a\0", 3, "", "a"); - _test_uuid("5d79494e-c4ba-31a6-80a2-d6016ccd7e17", "a\0a\0", 4, "a", "a"); - _test_uuid("fd698d86-1b60-3ebe-855f-7aada9950a8d", "aa\0a\0", 5, "aa", "a"); - _test_uuid("8c573b48-0f01-30ba-bb94-c5f59f4fe517", "\0aa\0", 4, "", "aa"); - _test_uuid("2bdd3d46-eb83-3c53-a41b-a724d04b5544", "a\0aa\0", 5, "a", "aa"); - _test_uuid("13d4b780-07c1-3ba7-b449-81c4844ef039", "aa\0aa\0", 6, "aa", "aa"); - _test_uuid("dd265bf7-c05a-3037-9939-b9629858a477", "a\0b\0", 4, "a", "b"); + _check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "457229f4-fe49-32f5-8b09-c531d81f44d9", + "x", + 1, + NULL, + -1); + check_uuid(NM_UUID_TYPE_VERSION3, &nm_uuid_ns_1, "b07c334a-399b-32de-8d50-58e4e08f98e3", ""); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "b8a426cb-bcb5-30a3-bd8f-6786fea72df9", + "\0", + ""); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "9232afda-85fc-3b8f-8736-4f99c8d5db9c", + "_n", + NULL); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "12a4a982-7aae-39e1-951e-41aeb1250959", + "a\0", + "a"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "69e22c7e-f89f-3a43-b239-1cb52ed8db69", + "aa\0", + "aa"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "59829fd3-5ad5-3d90-a7b0-4911747e4088", + "\0\0", + "", + ""); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "01ad0e06-6c50-3384-8d86-ddab81421425", + "a\0\0", + "a", + ""); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "e1ed8647-9ed3-3ec8-8c6d-e8204524d71d", + "aa\0\0", + "aa", + ""); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "fb1c7cd6-275c-3489-9382-83b900da8af0", + "\0a\0", + "", + "a"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "5d79494e-c4ba-31a6-80a2-d6016ccd7e17", + "a\0a\0", + "a", + "a"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "f36cec99-1db8-3baa-8c3f-13e13d980318", + "a\0a\0001_1n", + "a", + NULL, + "a"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "fd698d86-1b60-3ebe-855f-7aada9950a8d", + "aa\0a\0", + "aa", + "a"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "8c573b48-0f01-30ba-bb94-c5f59f4fe517", + "\0aa\0", + "", + "aa"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "2bdd3d46-eb83-3c53-a41b-a724d04b5544", + "a\0aa\0", + "a", + "aa"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "13d4b780-07c1-3ba7-b449-81c4844ef039", + "aa\0aa\0", + "aa", + "aa"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_1, + "dd265bf7-c05a-3037-9939-b9629858a477", + "a\0b\0", + "a", + "b"); + + check_uuid(NM_UUID_TYPE_VERSION5, + _uuid(NM_UUID_NS_URL), + "dd247a64-df22-5d30-8087-0bd709f6941a", + "a\0b\0", + "a", + "b"); + check_uuid(NM_UUID_TYPE_VERSION5, + _uuid(NM_UUID_NS_URL), + "cbb93d73-085d-5072-94cd-a394b8149993", + "\0b\0", + "", + "b"); + check_uuid(NM_UUID_TYPE_VERSION5, + _uuid(NM_UUID_NS_URL), + "db3dfd17-c785-509d-a0ca-740fdd68dc68", + "\0b\00011_n", + "", + "b", + NULL); + check_uuid(NM_UUID_TYPE_VERSION3, + _uuid(NM_UUID_NS_URL), + "916dcdd8-5042-3b9b-9763-4312a31e5735", + "aa\0a\0", + "aa", + "a"); + check_uuid(NM_UUID_TYPE_VERSION3, + NULL, + "1700bb72-7116-3d1f-8cd2-6d074a40a3a9", + "aa\0a\0", + "aa", + "a"); + check_uuid(NM_UUID_TYPE_VERSION3, + &nm_uuid_ns_zero, + "1700bb72-7116-3d1f-8cd2-6d074a40a3a9", + "aa\0a\0", + "aa", + "a"); + check_uuid(NM_UUID_TYPE_VERSION5, + NULL, + "03c5de66-28ad-5a2e-8ed3-e256f3218900", + "aa\0a\0", + "aa", + "a"); + check_uuid(NM_UUID_TYPE_VERSION5, + &nm_uuid_ns_zero, + "03c5de66-28ad-5a2e-8ed3-e256f3218900", + "aa\0a\0", + "aa", + "a"); + check_uuid(NM_UUID_TYPE_LEGACY, + NULL, + "c38f63cf-1e50-ad7f-ae26-50f85cc5da47", + "aa\0a\0", + "aa", + "a"); } static void @@ -8287,7 +8479,7 @@ test_nm_utils_strstrdictkey(void) const char *v1; const char *v2; NMUtilsStrStrDictKey *v_static; - } * val1, *val2, + } *val1, *val2, values[] = { {NULL, NULL}, {"", NULL}, @@ -8787,19 +8979,15 @@ _test_find_binary_search_do(const int *array, gsize len) expected_result = nm_utils_ptrarray_find_first(parray, len, pneedle); - idx = nm_utils_ptrarray_find_binary_search_range(parray, - len, - pneedle, - _test_find_binary_search_cmp, - NULL, - &idx_first, - &idx_last); + idx = nm_ptrarray_find_bsearch_range(parray, + len, + pneedle, + _test_find_binary_search_cmp, + NULL, + &idx_first, + &idx_last); - idx2 = nm_utils_ptrarray_find_binary_search(parray, - len, - pneedle, - _test_find_binary_search_cmp, - NULL); + idx2 = nm_ptrarray_find_bsearch(parray, len, pneedle, _test_find_binary_search_cmp, NULL); g_assert_cmpint(idx, ==, idx2); if (expected_result >= 0) { @@ -8864,12 +9052,12 @@ _test_find_binary_search_do_uint32(const int *int_array, gsize len) expected_result = idx; } - idx = nm_utils_array_find_binary_search(array, - sizeof(guint32), - len, - &NEEDLE, - nm_cmp_uint32_p_with_data, - NULL); + idx = nm_array_find_bsearch(array, + len, + sizeof(guint32), + &NEEDLE, + nm_cmp_uint32_p_with_data, + NULL); if (expected_result >= 0) g_assert_cmpint(expected_result, ==, idx); else { @@ -8963,29 +9151,25 @@ test_nm_utils_ptrarray_find_binary_search_with_duplicates(void) for (i = 0; i < i_len + BIN_SEARCH_W_DUPS_JITTER; i++) { gconstpointer p = GINT_TO_POINTER(i); - idx = nm_utils_ptrarray_find_binary_search_range(arr, - i_len, - p, - _test_bin_search2_cmp, - NULL, - &idx_first, - &idx_last); + idx = nm_ptrarray_find_bsearch_range(arr, + i_len, + p, + _test_bin_search2_cmp, + NULL, + &idx_first, + &idx_last); idx_first2 = nm_utils_ptrarray_find_first(arr, i_len, p); - idx2 = nm_utils_array_find_binary_search(arr, - sizeof(gpointer), - i_len, - &p, - _test_bin_search2_cmp_p, - NULL); + idx2 = nm_array_find_bsearch(arr, + i_len, + sizeof(gpointer), + &p, + _test_bin_search2_cmp_p, + NULL); g_assert_cmpint(idx, ==, idx2); - idx2 = nm_utils_ptrarray_find_binary_search(arr, - i_len, - p, - _test_bin_search2_cmp, - NULL); + idx2 = nm_ptrarray_find_bsearch(arr, i_len, p, _test_bin_search2_cmp, NULL); g_assert_cmpint(idx, ==, idx2); if (idx_first2 < 0) { @@ -9791,7 +9975,7 @@ test_route_attributes_parse(void) g_assert(!ht); g_clear_error(&error); - ht = nm_utils_parse_variant_attributes("mtu.1400 src.1\\.2\\.3\\.4 ", + ht = nm_utils_parse_variant_attributes("mtu.1400 weight.5 src.1\\.2\\.3\\.4 ", ' ', '.', FALSE, @@ -9804,6 +9988,11 @@ test_route_attributes_parse(void) g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); g_assert_cmpuint(g_variant_get_uint32(variant), ==, 1400); + variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_WEIGHT); + g_assert(variant); + g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); + g_assert_cmpuint(g_variant_get_uint32(variant), ==, 5); + variant = g_hash_table_lookup(ht, NM_IP_ROUTE_ATTRIBUTE_SRC); g_assert(variant); g_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)); @@ -10255,8 +10444,8 @@ static void test_nm_ip_addr_zero(void) { in_addr_t a4 = nmtst_inet4_from_string("0.0.0.0"); - struct in6_addr a6 = *nmtst_inet6_from_string("::"); - char buf[NM_UTILS_INET_ADDRSTRLEN]; + struct in6_addr a6 = nmtst_inet6_from_string("::"); + char buf[NM_INET_ADDRSTRLEN]; NMIPAddr a = NM_IP_ADDR_INIT; g_assert(memcmp(&a, &nm_ip_addr_zero, sizeof(a)) == 0); @@ -10267,11 +10456,11 @@ test_nm_ip_addr_zero(void) g_assert(memcmp(&nm_ip_addr_zero, &a4, sizeof(a4)) == 0); g_assert(memcmp(&nm_ip_addr_zero, &a6, sizeof(a6)) == 0); - g_assert_cmpstr(_nm_utils_inet4_ntop(nm_ip_addr_zero.addr4, buf), ==, "0.0.0.0"); - g_assert_cmpstr(_nm_utils_inet6_ntop(&nm_ip_addr_zero.addr6, buf), ==, "::"); + g_assert_cmpstr(nm_inet4_ntop(nm_ip_addr_zero.addr4, buf), ==, "0.0.0.0"); + g_assert_cmpstr(nm_inet6_ntop(&nm_ip_addr_zero.addr6, buf), ==, "::"); - g_assert_cmpstr(nm_utils_inet_ntop(AF_INET, &nm_ip_addr_zero, buf), ==, "0.0.0.0"); - g_assert_cmpstr(nm_utils_inet_ntop(AF_INET6, &nm_ip_addr_zero, buf), ==, "::"); + g_assert_cmpstr(nm_inet_ntop(AF_INET, &nm_ip_addr_zero, buf), ==, "0.0.0.0"); + g_assert_cmpstr(nm_inet_ntop(AF_INET6, &nm_ip_addr_zero, buf), ==, "::"); G_STATIC_ASSERT_EXPR(sizeof(a) == sizeof(a.array)); } @@ -10951,6 +11140,218 @@ test_direct_string_is_refstr(void) /*****************************************************************************/ +static void +test_connection_path(void) +{ + gs_unref_object NMConnection *conn = NULL; + const char *const PATH = "/org/freedesktop/NetworkManager/Settings/171950003017"; + const char *path; + NMRefString *rstr; + + g_assert(!nmtst_ref_string_find(PATH)); + + conn = nmtst_create_minimal_connection("test_setting_ip6_gateway", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + + g_assert(!nm_connection_get_path(conn)); + g_assert(!nmtst_ref_string_find(PATH)); + + nm_connection_set_path(conn, PATH); + + path = nm_connection_get_path(conn); + g_assert_cmpstr(path, ==, PATH); + + /* nm_connection_get_path() gives a NMRefString. This is an + * implementation detail, but libnm (which statically links with + * libnm-core) may choose to rely on that. */ + rstr = nmtst_ref_string_find(PATH); + g_assert(rstr); + g_assert(NM_REF_STRING_UPCAST(path) == rstr); + + g_clear_object(&conn); + + g_assert(!nmtst_ref_string_find(PATH)); +} + +/*****************************************************************************/ + +static void +_t_dnsname_1(const char *str, const char *exp_addr, const char *exp_server_name) +{ + int addr_family; + NMIPAddr exp_addr_bin; + gboolean addr_family_request; + gboolean r; + int detect_addr_family; + NMIPAddr detect_addr; + const char *detect_server_name; + int *p_detect_addr_family = &detect_addr_family; + NMIPAddr *p_detect_addr = &detect_addr; + const char **p_detect_server_name = &detect_server_name; + char str_construct_buf[100]; + char str_construct_buf2[100]; + const char *str_construct; + const char *str_construct2; + gsize l; + const char *str_normalized; + gs_free char *str_normalized_alloc = NULL; + + g_assert(str); + g_assert(exp_addr); + + r = nm_inet_parse_bin(AF_UNSPEC, exp_addr, &addr_family, &exp_addr_bin); + g_assert(r); + g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + + addr_family_request = nmtst_get_rand_bool(); + if (nmtst_get_rand_bool()) + p_detect_addr = NULL; + if ((addr_family_request || !p_detect_addr) && nmtst_get_rand_bool()) + p_detect_addr_family = NULL; + if (nmtst_get_rand_bool()) + p_detect_server_name = NULL; + + r = nm_utils_dnsname_parse(addr_family_request ? addr_family : AF_UNSPEC, + str, + p_detect_addr_family, + p_detect_addr, + p_detect_server_name); + g_assert(r); + + if (p_detect_addr_family) + g_assert_cmpint(addr_family, ==, detect_addr_family); + if (p_detect_addr) + g_assert_cmpstr(nmtst_inet_to_string(addr_family, &detect_addr), ==, exp_addr); + if (p_detect_server_name) + g_assert_cmpstr(detect_server_name, ==, exp_server_name); + + r = nm_utils_dnsname_parse(addr_family == AF_INET ? AF_INET6 : AF_INET, + str, + p_detect_addr_family, + p_detect_addr, + p_detect_server_name); + g_assert(!r); + + /* Construct the expected value. */ + str_construct = nm_utils_dnsname_construct(addr_family, + &exp_addr_bin, + exp_server_name, + str_construct_buf, + sizeof(str_construct_buf)); + g_assert(str_construct); + g_assert(str_construct == str_construct_buf); + g_assert(strlen(str_construct) < sizeof(str_construct_buf)); + + /* Check that a too short buffer causes truncation. */ + l = nmtst_get_rand_uint32() % (strlen(str_construct) + 10); + str_construct2 = nm_utils_dnsname_construct(addr_family, + &exp_addr_bin, + exp_server_name, + str_construct_buf2, + l); + if (str_construct2) { + g_assert(str_construct2 == str_construct_buf2); + g_assert_cmpstr(str_construct2, ==, str_construct); + g_assert(l > strlen(str_construct)); + } else + g_assert(l <= strlen(str_construct)); + + if (!nm_streq(str_construct, str)) { + _t_dnsname_1(str_construct, exp_addr, exp_server_name); + } + + str_normalized = nm_utils_dnsname_normalize(nmtst_get_rand_bool() ? addr_family : AF_UNSPEC, + str, + &str_normalized_alloc); + g_assert(str_normalized); + if (str_normalized_alloc) { + g_assert(str_normalized == str_normalized_alloc); + g_assert_cmpstr(str_normalized, !=, str); + } else { + g_assert(str == str_normalized); + } + g_assert_cmpstr(str_normalized, ==, str_construct); + + nm_clear_g_free(&str_normalized_alloc); + str_normalized = nm_utils_dnsname_normalize(addr_family == AF_INET ? AF_INET6 : AF_INET, + str, + &str_normalized_alloc); + g_assert(!str_normalized); + g_assert(!str_normalized_alloc); +} + +static void +_t_dnsname_0(const char *str) +{ + gboolean addr_family_request; + int detect_addr_family; + NMIPAddr detect_addr; + const char *detect_server_name; + int *p_detect_addr_family = &detect_addr_family; + NMIPAddr *p_detect_addr = &detect_addr; + const char **p_detect_server_name = &detect_server_name; + const char *str_normalized; + gs_free char *str_normalized_alloc = NULL; + gboolean r; + + g_assert(str); + + addr_family_request = nmtst_get_rand_bool(); + if (nmtst_get_rand_bool()) + p_detect_addr = NULL; + if ((addr_family_request || !p_detect_addr) && nmtst_get_rand_bool()) + p_detect_addr_family = NULL; + if (nmtst_get_rand_bool()) + p_detect_server_name = NULL; + + r = nm_utils_dnsname_parse(addr_family_request ? nmtst_rand_select(AF_INET, AF_INET6) + : AF_UNSPEC, + str, + p_detect_addr_family, + p_detect_addr, + p_detect_server_name); + g_assert(!r); + + str_normalized = nm_utils_dnsname_normalize(nmtst_rand_select(AF_UNSPEC, AF_INET, AF_INET6), + str, + &str_normalized_alloc); + g_assert(!str_normalized); + g_assert(!str_normalized_alloc); +} + +static void +test_dnsname(void) +{ + _t_dnsname_1("1.2.3.4", "1.2.3.4", NULL); + _t_dnsname_1("1.2.3.4#foo", "1.2.3.4", "foo"); + _t_dnsname_1("1::#x", "1::", "x"); + _t_dnsname_1("1::0#x", "1::", "x"); + _t_dnsname_1("192.168.0.1", "192.168.0.1", NULL); + _t_dnsname_1("192.168.0.1#test.com", "192.168.0.1", "test.com"); + _t_dnsname_1("fe80::18", "fe80::18", NULL); + _t_dnsname_1("fe80::18#hoge.com", "fe80::18", "hoge.com"); + + _t_dnsname_0("1.2.3.4#"); + _t_dnsname_0("1::0#"); + _t_dnsname_0("192.168.0.1:53"); + _t_dnsname_0("192.168.0.1:53#example.com"); + _t_dnsname_0("fe80::18%19"); + _t_dnsname_0("fe80::18%lo"); + _t_dnsname_0("[fe80::18]:53"); + _t_dnsname_0("[fe80::18]:53%19"); + _t_dnsname_0("[fe80::18]:53%lo"); + _t_dnsname_0("fe80::18%19#hoge.com"); + _t_dnsname_0("[fe80::18]:53#hoge.com"); + _t_dnsname_0("[fe80::18]:53%19"); + _t_dnsname_0("[fe80::18]:53%19#hoge.com"); + _t_dnsname_0("[fe80::18]:53%lo"); + _t_dnsname_0("[fe80::18]:53%lo#hoge.com"); +} + +/*****************************************************************************/ + NMTST_DEFINE(); int @@ -11257,7 +11658,7 @@ main(int argc, char **argv) g_test_add_func("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64); g_test_add_func("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two); - g_test_add_func("/core/general/nm_utils_ptrarray_find_binary_search_range", + g_test_add_func("/core/general/nm_ptrarray_find_bsearch_range", test_nm_utils_ptrarray_find_binary_search); g_test_add_func("/core/general/nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates); @@ -11296,6 +11697,8 @@ main(int argc, char **argv) g_test_add_func("/core/general/test_system_encodings", test_system_encodings); g_test_add_func("/core/general/test_direct_string_is_refstr", test_direct_string_is_refstr); + g_test_add_func("/core/general/test_connection_path", test_connection_path); + g_test_add_func("/core/general/test_dnsname", test_dnsname); return g_test_run(); } diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c index a4e3932a..de60afd1 100644 --- a/src/libnm-core-impl/tests/test-setting.c +++ b/src/libnm-core-impl/tests/test-setting.c @@ -121,7 +121,7 @@ test_nm_meta_setting_types_by_priority(void) G_STATIC_ASSERT_EXPR(_NM_META_SETTING_TYPE_NUM == G_N_ELEMENTS(nm_meta_setting_types_by_priority)); - G_STATIC_ASSERT_EXPR(_NM_META_SETTING_TYPE_NUM == 52); + G_STATIC_ASSERT_EXPR(_NM_META_SETTING_TYPE_NUM == 54); arr = g_ptr_array_new_with_free_func(g_object_unref); @@ -3755,7 +3755,7 @@ test_roundtrip_conversion(gconstpointer test_data) for (is_ipv4 = 0; is_ipv4 < 2; is_ipv4++) { g_assert(NM_IS_SETTING_IP_CONFIG(s_ip.s_x[is_ipv4])); for (i = 0; i < 3; i++) { - char addrstr[NM_UTILS_INET_ADDRSTRLEN]; + char addrstr[NM_INET_ADDRSTRLEN]; nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr = NULL; @@ -4166,6 +4166,88 @@ test_routing_rule(gconstpointer test_data) /*****************************************************************************/ static void +test_ranges(void) +{ + GError *error = NULL; + NMRange *r1; + NMRange *r2; + guint64 start; + guint64 end; + char *str = NULL; + char *str2 = NULL; + + r1 = nm_range_from_str("99", &error); + nmtst_assert_success(r1, error); + nm_range_get_range(r1, &start, &end); + g_assert_cmpint(start, ==, 99); + g_assert_cmpint(end, ==, 99); + str = nm_range_to_str(r1); + g_assert_cmpstr(str, ==, "99"); + nm_clear_g_free(&str); + nm_range_unref(r1); + + r1 = nm_range_from_str("1000-2000", &error); + nmtst_assert_success(r1, error); + nm_range_get_range(r1, &start, &end); + g_assert_cmpint(start, ==, 1000); + g_assert_cmpint(end, ==, 2000); + str = nm_range_to_str(r1); + g_assert_cmpstr(str, ==, "1000-2000"); + nm_clear_g_free(&str); + nm_range_unref(r1); + + r1 = nm_range_from_str("0", &error); + nmtst_assert_success(r1, error); + nm_range_unref(r1); + + r1 = nm_range_from_str("-1", &error); + nmtst_assert_no_success(r1, error); + g_clear_error(&error); + + r1 = nm_range_from_str("foobar", &error); + nmtst_assert_no_success(r1, error); + g_clear_error(&error); + + r1 = nm_range_from_str("200-100", &error); + nmtst_assert_no_success(r1, error); + g_clear_error(&error); + + r1 = nm_range_from_str("100-200", &error); + nmtst_assert_success(r1, error); + r2 = nm_range_from_str("100-200", &error); + nmtst_assert_success(r2, error); + g_assert_cmpint(nm_range_cmp(r1, r2), ==, 0); + nm_range_unref(r1); + nm_range_unref(r2); + + r1 = nm_range_from_str("100-200", &error); + nmtst_assert_success(r1, error); + r2 = nm_range_from_str("1", &error); + nmtst_assert_success(r2, error); + g_assert_cmpint(nm_range_cmp(r1, r2), ==, 1); + nm_range_ref(r1); + nm_range_unref(r1); + nm_range_unref(r1); + nm_range_unref(r2); + + r1 = nm_range_new(G_MAXUINT64 - 1, G_MAXUINT64); + g_assert(r1); + str = nm_range_to_str(r1); + g_assert_cmpstr(str, ==, "18446744073709551614-18446744073709551615"); + r2 = nm_range_from_str(str, &error); + nmtst_assert_success(r2, error); + str2 = nm_range_to_str(r2); + g_assert_cmpstr(str, ==, str2); + g_assert_cmpint(nm_range_cmp(r1, r2), ==, 0); + nm_range_unref(r1); + nm_range_unref(r2); + nm_clear_g_free(&str); + nm_clear_g_free(&str2); +} + +/*****************************************************************************/ + +static void test_parse_tc_handle(void) { #define _parse_tc_handle(str, exp) \ @@ -4303,7 +4385,7 @@ _PROP_IDX_OWNER(GHashTable *h_property_types, const NMSettInfoPropertType *prope g_assert(arr); g_assert(arr->len > 0); - idx = g_array_index(arr, guint, 0); + idx = nm_g_array_first(arr, guint); meta_type = (idx & 0xFFu); prop_idx = idx >> 8; @@ -5069,6 +5151,84 @@ test_6lowpan_1(void) /*****************************************************************************/ static void +test_settings_dns(void) +{ + int i_run; + + for (i_run = 0; i_run < 10; i_run++) { + gs_unref_object NMConnection *con1 = NULL; + gs_unref_object NMConnection *con2 = NULL; + int IS_IPv4; + guint n_dns; + guint i; + gboolean same = TRUE; + + con1 = + nmtst_create_minimal_connection("test-dns", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nmtst_connection_normalize(con1); + + con2 = nmtst_connection_duplicate_and_normalize(con1); + + nmtst_assert_connection_equals(con1, nmtst_get_rand_bool(), con2, nmtst_get_rand_bool()); + + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + const char *nameservers[2][7] = { + [0] = + { + "11:22::b:0", + "11:22::b:1#hello1", + "11:22::b:2", + "11:22::b:3#hello2", + "11:22::b:4", + "11:22::b:5", + "bogus6", + }, + [1] = + { + "1.1.1.0", + "1.1.1.1#foo1", + "1.1.1.2", + "1.1.1.3#foo2", + "1.1.1.4", + "1.1.1.5", + "bogus4", + }, + }; + GType gtype = IS_IPv4 ? NM_TYPE_SETTING_IP4_CONFIG : NM_TYPE_SETTING_IP6_CONFIG; + NMSettingIPConfig *s_ip1 = _nm_connection_get_setting(con1, gtype); + NMSettingIPConfig *s_ip2 = _nm_connection_get_setting(con2, gtype); + + n_dns = nmtst_get_rand_uint32() % G_N_ELEMENTS(nameservers[0]); + for (i = 0; i < n_dns; i++) { + const char *d = + nameservers[IS_IPv4][nmtst_get_rand_uint32() % G_N_ELEMENTS(nameservers[0])]; + + if (!nmtst_get_rand_one_case_in(4)) + nm_setting_ip_config_add_dns(s_ip1, d); + if (!nmtst_get_rand_one_case_in(4)) + nm_setting_ip_config_add_dns(s_ip2, d); + } + + if (nm_strv_ptrarray_cmp(_nm_setting_ip_config_get_dns_array(s_ip1), + _nm_setting_ip_config_get_dns_array(s_ip2)) + != 0) + same = FALSE; + } + + _nm_utils_is_manager_process = nmtst_get_rand_bool(); + if (same) { + nmtst_assert_connection_equals(con1, FALSE, con2, FALSE); + g_assert(nm_connection_compare(con1, con2, NM_SETTING_COMPARE_FLAG_EXACT)); + } else { + g_assert(!nm_connection_compare(con1, con2, NM_SETTING_COMPARE_FLAG_EXACT)); + } + _nm_utils_is_manager_process = FALSE; + } +} + +/*****************************************************************************/ + +static void test_bond_meta(void) { gs_unref_object NMConnection *con = NULL; @@ -5170,6 +5330,8 @@ main(int argc, char **argv) g_test_add_func("/libnm/settings/6lowpan/1", test_6lowpan_1); + g_test_add_func("/libnm/settings/dns", test_settings_dns); + g_test_add_func("/libnm/settings/sriov/vf", test_sriov_vf); g_test_add_func("/libnm/settings/sriov/vf-dup", test_sriov_vf_dup); g_test_add_func("/libnm/settings/sriov/vf-vlan", test_sriov_vf_vlan); @@ -5236,6 +5398,8 @@ main(int argc, char **argv) g_test_add_data_func("/libnm/settings/routing-rule/1", GINT_TO_POINTER(0), test_routing_rule); + g_test_add_func("/libnm/settings/ranges", test_ranges); + g_test_add_func("/libnm/parse-tc-handle", test_parse_tc_handle); g_test_add_func("/libnm/test_team_setting", test_team_setting); |