diff options
| author | Michael Biebl <biebl@debian.org> | 2022-12-03 22:59:09 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2022-12-03 22:59:09 +0100 |
| commit | 06356c8ac470c1fa46f881b0598ec48a653e69ae (patch) | |
| tree | 42e7714b4caedf4d23ebefd42d8d0afebc6f3569 /src | |
| parent | 78ecd0c8a4a337e38470f3fae5db74daf61ba86a (diff) | |
| parent | 372b62c2c25eb1f2e811f84849e9b69c40ae6245 (diff) | |
Merge branch 'debian/master' into debian/bullseye-backports
Diffstat (limited to 'src')
149 files changed, 1880 insertions, 686 deletions
diff --git a/src/core/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c index 8b0b4845..f5b7666b 100644 --- a/src/core/NetworkManagerUtils.c +++ b/src/core/NetworkManagerUtils.c @@ -978,6 +978,7 @@ nm_ip_routing_rule_to_platform(const NMIPRoutingRule *rule, NMPlatformRoutingRul .start = uid_range_start, .end = uid_range_end, }, + .protocol = RTPROT_STATIC, }; nm_ip_routing_rule_get_xifname_bin(rule, TRUE, out_pl->iifname); diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 44bb316d..3e083de4 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -395,61 +395,57 @@ _platform_lnk_bond_init_from_setting(NMSettingBond *s_bond, NMPlatformLnkBond *p { const char *opt_value; +#define _v_fcn(fcn, s_bond, opt) (fcn(nm_setting_bond_get_option_normalized((s_bond), (opt)))) +#define _v_u8(s_bond, opt) _nm_setting_bond_opt_value_as_u8((s_bond), (opt)) +#define _v_u16(s_bond, opt) _nm_setting_bond_opt_value_as_u16((s_bond), (opt)) +#define _v_u32(s_bond, opt) _nm_setting_bond_opt_value_as_u32((s_bond), (opt)) +#define _v_intbool(s_bond, opt) _nm_setting_bond_opt_value_as_intbool((s_bond), (opt)) + *props = (NMPlatformLnkBond){ - .mode = _nm_setting_bond_mode_from_string( - nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_MODE)), + .mode = _v_fcn(_nm_setting_bond_mode_from_string, s_bond, NM_SETTING_BOND_OPTION_MODE), .primary = _setting_bond_primary_opt_as_ifindex(s_bond), - .miimon = _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_MIIMON), - .updelay = _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_UPDELAY), - .downdelay = _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY), - .arp_interval = - _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL), - .resend_igmp = - _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP), - .min_links = _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_MIN_LINKS), - .lp_interval = - _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL), - .packets_per_port = - _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE), - .peer_notif_delay = - _nm_setting_bond_opt_value_as_u32(s_bond, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY), - .arp_all_targets = _nm_setting_bond_arp_all_targets_from_string( - nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS)), - .arp_validate = _nm_setting_bond_arp_validate_from_string( - nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE)), - .ad_actor_sys_prio = - _nm_setting_bond_opt_value_as_u16(s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO), - .ad_user_port_key = - _nm_setting_bond_opt_value_as_u16(s_bond, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY), - .primary_reselect = _nm_setting_bond_primary_reselect_from_string( - nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT)), - .fail_over_mac = _nm_setting_bond_fail_over_mac_from_string( - nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC)), - .xmit_hash_policy = _nm_setting_bond_xmit_hash_policy_from_string( - nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY)), - .num_grat_arp = - _nm_setting_bond_opt_value_as_u8(s_bond, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP), - .all_ports_active = - _nm_setting_bond_opt_value_as_u8(s_bond, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE), - .lacp_rate = _nm_setting_bond_lacp_rate_from_string( - nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_LACP_RATE)), - .ad_select = _nm_setting_bond_ad_select_from_string( - nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_AD_SELECT)), + .miimon = _v_u32(s_bond, NM_SETTING_BOND_OPTION_MIIMON), + .updelay = _v_u32(s_bond, NM_SETTING_BOND_OPTION_UPDELAY), + .downdelay = _v_u32(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY), + .arp_interval = _v_u32(s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL), + .resend_igmp = _v_u32(s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP), + .min_links = _v_u32(s_bond, NM_SETTING_BOND_OPTION_MIN_LINKS), + .lp_interval = _v_u32(s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL), + .packets_per_port = _v_u32(s_bond, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE), + .peer_notif_delay = _v_u32(s_bond, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY), + .arp_all_targets = _v_fcn(_nm_setting_bond_arp_all_targets_from_string, + s_bond, + NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS), + .arp_validate = _v_fcn(_nm_setting_bond_arp_validate_from_string, + s_bond, + NM_SETTING_BOND_OPTION_ARP_VALIDATE), + .ad_actor_sys_prio = _v_u16(s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO), + .ad_user_port_key = _v_u16(s_bond, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY), + .primary_reselect = _v_fcn(_nm_setting_bond_primary_reselect_from_string, + s_bond, + NM_SETTING_BOND_OPTION_PRIMARY_RESELECT), + .fail_over_mac = _v_fcn(_nm_setting_bond_fail_over_mac_from_string, + s_bond, + NM_SETTING_BOND_OPTION_FAIL_OVER_MAC), + .xmit_hash_policy = _v_fcn(_nm_setting_bond_xmit_hash_policy_from_string, + s_bond, + NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY), + .num_grat_arp = _v_u8(s_bond, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP), + .all_ports_active = _v_u8(s_bond, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE), + .lacp_rate = _v_fcn(_nm_setting_bond_lacp_rate_from_string, + s_bond, + NM_SETTING_BOND_OPTION_LACP_RATE), + .ad_select = _v_fcn(_nm_setting_bond_ad_select_from_string, + s_bond, + NM_SETTING_BOND_OPTION_AD_SELECT), + .use_carrier = _v_intbool(s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER), + .tlb_dynamic_lb = _v_intbool(s_bond, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB), }; nm_ether_addr_from_string( &props->ad_actor_system, nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)); - opt_value = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER); - if (opt_value != NULL) - props->use_carrier = _nm_utils_ascii_str_to_bool(opt_value, FALSE); - - opt_value = - nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB); - if (opt_value != NULL) - props->tlb_dynamic_lb = _nm_utils_ascii_str_to_bool(opt_value, FALSE); - opt_value = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); if (opt_value != NULL) props->arp_ip_targets_num = @@ -459,7 +455,6 @@ _platform_lnk_bond_init_from_setting(NMSettingBond *s_bond, NMPlatformLnkBond *p props->updelay_has = props->miimon_has && props->miimon; props->downdelay_has = props->miimon_has && props->miimon; props->peer_notif_delay_has = (props->miimon || props->arp_interval) && props->peer_notif_delay; - props->arp_all_targets_has = props->arp_interval && props->arp_all_targets; props->resend_igmp_has = props->resend_igmp != 1; props->lp_interval_has = props->lp_interval != 1; props->tlb_dynamic_lb_has = NM_IN_SET(props->mode, NM_BOND_MODE_TLB, NM_BOND_MODE_ALB); @@ -493,6 +488,10 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) if (!nm_device_hw_addr_set_cloned(device, nm_device_get_applied_connection(device), FALSE)) ret = NM_ACT_STAGE_RETURN_FAILURE; } + + /* This is a workaround because netlink do not support ifname as primary */ + set_bond_attr_or_default(device, s_bond, NM_SETTING_BOND_OPTION_PRIMARY); + nm_device_bring_up(device, TRUE, NULL); return ret; diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c index 40c6d208..4788cdc6 100644 --- a/src/core/devices/nm-device-ethernet.c +++ b/src/core/devices/nm-device-ethernet.c @@ -1354,6 +1354,11 @@ wake_on_lan_enable(NMDevice *device) if (s_wired) { wol = nm_setting_wired_get_wake_on_lan(s_wired); password = nm_setting_wired_get_wake_on_lan_password(s_wired); + + /* NMSettingWired does not reject invalid flags. Filter them out here. */ + wol = (wol + & (NM_SETTING_WIRED_WAKE_ON_LAN_ALL | NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS)); + if (wol != NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT) goto found; } @@ -1370,9 +1375,14 @@ wake_on_lan_enable(NMDevice *device) nm_log_dbg(LOGD_ETHER, "invalid default value %u for wake-on-lan", (guint) wol); wol = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT; } + + wol = wol & (NM_SETTING_WIRED_WAKE_ON_LAN_ALL | NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS); + if (wol != NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT) goto found; + wol = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; + found: return nm_platform_ethtool_set_wake_on_lan(nm_device_get_platform(device), nm_device_get_ifindex(device), diff --git a/src/core/devices/nm-device-private.h b/src/core/devices/nm-device-private.h index b54aed6a..31424d5c 100644 --- a/src/core/devices/nm-device-private.h +++ b/src/core/devices/nm-device-private.h @@ -89,7 +89,10 @@ nm_device_devip_set_state(NMDevice *self, nm_assert(NM_IS_DEVICE(self)); nm_assert_addr_family_or_unspec(addr_family); nm_assert(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd)); - nm_assert(NM_IN_SET(ip_state, NM_DEVICE_IP_STATE_PENDING, NM_DEVICE_IP_STATE_READY)); + nm_assert(NM_IN_SET(ip_state, + NM_DEVICE_IP_STATE_NONE, + NM_DEVICE_IP_STATE_PENDING, + NM_DEVICE_IP_STATE_READY)); nm_device_devip_set_state_full(self, addr_family, ip_state, l3cd, NM_DEVICE_STATE_REASON_NONE); } diff --git a/src/core/devices/nm-device-veth.c b/src/core/devices/nm-device-veth.c index 63dfd8bb..c3482e78 100644 --- a/src/core/devices/nm-device-veth.c +++ b/src/core/devices/nm-device-veth.c @@ -101,8 +101,8 @@ create_and_realize(NMDevice *device, peer = nm_setting_veth_get_peer(s_veth); peer_device = nm_manager_get_device(NM_MANAGER_GET, peer, NM_DEVICE_TYPE_VETH); if (peer_device) { - /* The veth device and its peer already exist. No need to create it again. */ - if (nm_streq0(nm_device_get_iface(nm_device_parent_get_device(peer_device)), iface)) + if (nm_device_parent_get_device(peer_device)) + /* The veth device and its peer already exist. No need to create it again. */ return TRUE; } diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index d63b902b..2cda9b0d 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -96,6 +96,8 @@ #define NM_DEVICE_AUTH_RETRIES_INFINITY -2 #define NM_DEVICE_AUTH_RETRIES_DEFAULT 3 +#define AUTOCONNECT_RESET_RETRIES_TIMER 300 + /*****************************************************************************/ typedef void (*ActivationHandleFunc)(NMDevice *self); @@ -761,6 +763,9 @@ typedef struct _NMDevicePrivate { GVariant *ports_variant; /* Array of port devices D-Bus path */ char *prop_ip_iface; /* IP interface D-Bus property */ + + int autoconnect_retries; + gint32 autoconnect_retries_blocked_until; } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -778,7 +783,9 @@ static void _dev_l3_cfg_commit_type_reset(NMDevice *self); static gboolean nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure); static void nm_device_slave_notify_enslave(NMDevice *self, gboolean success); -static void nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason); +static void nm_device_slave_notify_release(NMDevice *self, + NMDeviceStateReason reason, + ReleaseSlaveType release_type); static void _dev_ipll6_start(NMDevice *self); @@ -6236,7 +6243,7 @@ nm_device_master_release_slave(NMDevice *self, release_type >= RELEASE_SLAVE_TYPE_CONFIG); /* raise notifications about the release, including clearing is_enslaved. */ - nm_device_slave_notify_release(slave, reason); + nm_device_slave_notify_release(slave, reason, release_type); /* keep both alive until the end of the function. * Transfers ownership from slave_priv->master. */ @@ -6536,12 +6543,16 @@ device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink) g_return_if_fail(plink); - if (plink->master <= 0) - goto out; - - master = nm_manager_get_device_by_ifindex(NM_MANAGER_GET, plink->master); - plink_master = nm_platform_link_get(nm_device_get_platform(self), plink->master); - plink_master_keep_alive = nmp_object_ref(NMP_OBJECT_UP_CAST(plink_master)); + if (plink->master > 0) { + master = nm_manager_get_device_by_ifindex(NM_MANAGER_GET, plink->master); + plink_master = nm_platform_link_get(nm_device_get_platform(self), plink->master); + plink_master_keep_alive = nmp_object_ref(NMP_OBJECT_UP_CAST(plink_master)); + } else { + if (priv->master_ifindex == 0) + goto out; + master = NULL; + plink_master = NULL; + } if (master == NULL && plink_master && NM_IN_STRSET(plink_master->name, "ovs-system", "ovs-netdev") @@ -6646,7 +6657,6 @@ device_link_changed(gpointer user_data) NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gboolean ip_ifname_changed = FALSE; - gboolean hw_addr_changed; nm_auto_nmpobj const NMPObject *pllink_keep_alive = NULL; const NMPlatformLink *pllink; const char *str; @@ -6693,9 +6703,9 @@ device_link_changed(gpointer user_data) if (ifindex == nm_device_get_ip_ifindex(self)) _stats_update_counters_from_pllink(self, pllink); - had_hw_addr = (priv->hw_addr != NULL); - hw_addr_changed = nm_device_update_hw_address(self); - got_hw_addr = (!had_hw_addr && priv->hw_addr); + had_hw_addr = (priv->hw_addr != NULL); + nm_device_update_hw_address(self); + got_hw_addr = (!had_hw_addr && priv->hw_addr); nm_device_update_permanent_hw_address(self, FALSE); if (pllink->name[0] && !nm_streq(priv->iface, pllink->name)) { @@ -6746,8 +6756,6 @@ device_link_changed(gpointer user_data) /* Update DHCP, etc, if needed */ if (ip_ifname_changed) nm_device_update_dynamic_ip_setup(self, "IP interface changed"); - else if (hw_addr_changed) - nm_device_update_dynamic_ip_setup(self, "hw-address changed"); was_up = priv->up; priv->up = NM_FLAGS_HAS(pllink->n_ifi_flags, IFF_UP); @@ -8024,7 +8032,9 @@ nm_device_slave_notify_enslave(NMDevice *self, gboolean success) * Notifies a slave that it has been released, and why. */ static void -nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason) +nm_device_slave_notify_release(NMDevice *self, + NMDeviceStateReason reason, + ReleaseSlaveType release_type) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMConnection *connection = nm_device_get_applied_connection(self); @@ -8032,7 +8042,7 @@ nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason) g_return_if_fail(priv->master); - if (!priv->is_enslaved) + if (!priv->is_enslaved && release_type == RELEASE_SLAVE_TYPE_NO_CONFIG) return; if (priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state <= NM_DEVICE_STATE_ACTIVATED) { @@ -8956,7 +8966,7 @@ nm_device_emit_recheck_assume(gpointer user_data) priv = NM_DEVICE_GET_PRIVATE(self); priv->recheck_assume_id = 0; - if (!nm_device_get_act_request(self)) + if (!priv->queued_act_request && !nm_device_get_act_request(self)) g_signal_emit(self, signals[RECHECK_ASSUME], 0); return G_SOURCE_REMOVE; @@ -9954,6 +9964,7 @@ nm_device_devip_set_state_full(NMDevice *self, nm_assert_addr_family_or_unspec(addr_family); nm_assert(NM_IN_SET(ip_state, + NM_DEVICE_IP_STATE_NONE, NM_DEVICE_IP_STATE_PENDING, NM_DEVICE_IP_STATE_READY, NM_DEVICE_IP_STATE_FAILED)); @@ -9961,7 +9972,7 @@ nm_device_devip_set_state_full(NMDevice *self, nm_assert((ip_state != NM_DEVICE_IP_STATE_FAILED) == (failed_reason == NM_DEVICE_STATE_REASON_NONE)); - nm_assert((ip_state != NM_DEVICE_IP_STATE_FAILED) || !l3cd); + nm_assert(NM_IN_SET(ip_state, NM_DEVICE_IP_STATE_PENDING, NM_DEVICE_IP_STATE_READY) || !l3cd); p = _dev_ipdev_data(self, addr_family); @@ -12206,7 +12217,7 @@ _dev_ipsharedx_cleanup(NMDevice *self, int addr_family) } if (priv->ipshared_data_4.v4.firewall_config) { - nm_firewall_config_apply(priv->ipshared_data_4.v4.firewall_config, FALSE); + nm_firewall_config_apply_sync(priv->ipshared_data_4.v4.firewall_config, FALSE); nm_clear_pointer(&priv->ipshared_data_4.v4.firewall_config, nm_firewall_config_free); } @@ -12353,8 +12364,8 @@ _dev_ipshared4_start(NMDevice *self) goto out_fail; priv->ipshared_data_4.v4.firewall_config = - nm_firewall_config_new(ip_iface, ip4_addr.address, ip4_addr.plen); - nm_firewall_config_apply(priv->ipshared_data_4.v4.firewall_config, TRUE); + nm_firewall_config_new_shared(ip_iface, ip4_addr.address, ip4_addr.plen); + nm_firewall_config_apply_sync(priv->ipshared_data_4.v4.firewall_config, TRUE); priv->ipshared_data_4.v4.l3cd = nm_l3_config_data_ref(l3cd); _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_SHARED_4, l3cd, FALSE); @@ -16857,6 +16868,49 @@ nm_device_get_initial_hw_address(NMDevice *self) return NM_DEVICE_GET_PRIVATE(self)->hw_addr_initial; } +void +nm_device_set_autoconnect_retries(NMDevice *self, int tries) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + if (priv->autoconnect_retries != tries) { + _LOGT(LOGD_DEVICE, "autoconnect: retries set %d", tries); + priv->autoconnect_retries = tries; + } + + if (tries) + priv->autoconnect_retries_blocked_until = 0; /* we are not blocked anymore */ + else + priv->autoconnect_retries_blocked_until = + nm_utils_get_monotonic_timestamp_sec() + AUTOCONNECT_RESET_RETRIES_TIMER; +} + +int +nm_device_get_autoconnect_retries(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + return priv->autoconnect_retries; +} + +gint32 +nm_device_autoconnect_retries_blocked_until(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + return priv->autoconnect_retries_blocked_until; +} + +void +nm_device_autoconnect_retries_reset(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + /* default value, we will sync. with connection value when needed */ + priv->autoconnect_retries = -2; + priv->autoconnect_retries_blocked_until = 0; +} + /** * nm_device_spec_match_list: * @self: an #NMDevice @@ -17161,6 +17215,13 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean /* If the device is not supposed to have addresses, * return an immediate empty result.*/ if (!nm_device_get_applied_connection(self)) { + nm_clear_pointer(&priv->hostname_resolver_x[IS_IPv4], _hostname_resolver_free); + NM_SET_OUT(out_wait, FALSE); + return NULL; + } + + if (!priv->carrier) { + nm_clear_pointer(&priv->hostname_resolver_x[IS_IPv4], _hostname_resolver_free); NM_SET_OUT(out_wait, FALSE); return NULL; } @@ -17601,6 +17662,8 @@ nm_device_init(NMDevice *self) priv->sys_iface_state_ = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; priv->promisc_reset = NM_OPTION_BOOL_DEFAULT; + + priv->autoconnect_retries = -2; } static GObject * diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index de850e68..fea46bb7 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -464,6 +464,11 @@ const char *nm_device_get_permanent_hw_address_full(NMDevice *self, gboolean *out_is_fake); const char *nm_device_get_initial_hw_address(NMDevice *dev); +void nm_device_set_autoconnect_retries(NMDevice *self, int tries); +int nm_device_get_autoconnect_retries(NMDevice *self); +gint32 nm_device_autoconnect_retries_blocked_until(NMDevice *self); +void nm_device_autoconnect_retries_reset(NMDevice *self); + NMDhcpConfig *nm_device_get_dhcp_config(NMDevice *dev, int addr_family); NML3Cfg *nm_device_get_l3cfg(NMDevice *self); diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index e7c96852..d3e858a1 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -18,6 +18,7 @@ #include "nm-manager.h" #include "nm-setting-ovs-external-ids.h" #include "nm-priv-helper-call.h" +#include "libnm-platform/nm-platform.h" /*****************************************************************************/ @@ -120,6 +121,7 @@ enum { static guint signals[LAST_SIGNAL] = {0}; typedef struct { + NMPlatform *platform; GSocketConnection *conn; GCancellable *conn_cancellable; char buf[4096]; /* Input buffer */ @@ -135,8 +137,14 @@ typedef struct { GHashTable *bridges; /* bridge uuid => OpenvswitchBridge */ char *db_uuid; guint num_failures; - guint num_pending_deletions; bool ready : 1; + struct { + GPtrArray *interfaces; /* Interface names we are waiting to go away */ + GSource *timeout_source; /* After all deletions complete, wait this + * timeout for interfaces to disappear */ + gulong link_changed_id; /* Platform link-changed signal handle */ + guint num_pending_del; /* Number of ovsdb deletions pending */ + } cleanup; } NMOvsdbPrivate; struct _NMOvsdb { @@ -161,6 +169,7 @@ static void ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposin static void ovsdb_read(NMOvsdb *self); static void ovsdb_write(NMOvsdb *self); static void ovsdb_next_command(NMOvsdb *self); +static void cleanup_check_ready(NMOvsdb *self); /*****************************************************************************/ @@ -2283,21 +2292,114 @@ ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing) } static void -_check_ready(NMOvsdb *self) +cleanup_emit_ready(NMOvsdb *self, const char *reason) +{ + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + + _LOGT("cleanup: ready (%s)", reason); + + nm_clear_pointer(&priv->cleanup.interfaces, g_ptr_array_unref); + nm_clear_g_source_inst(&priv->cleanup.timeout_source); + nm_clear_g_signal_handler(priv->platform, &priv->cleanup.link_changed_id); + + priv->ready = TRUE; + g_signal_emit(self, signals[READY], 0); + nm_manager_unblock_failed_ovs_interfaces(nm_manager_get()); +} + +static gboolean +cleanup_timeout(NMOvsdb *self) +{ + cleanup_emit_ready(self, "timeout"); + return G_SOURCE_CONTINUE; +} + +static void +cleanup_link_cb(NMPlatform *platform, + int obj_type_i, + int ifindex, + NMPlatformLink *plink, + int change_type_i, + gpointer user_data) +{ + const NMPlatformSignalChangeType change_type = change_type_i; + + if (change_type != NM_PLATFORM_SIGNAL_REMOVED) + return; + + cleanup_check_ready(user_data); +} + +static void +cleanup_check_ready(NMOvsdb *self) { NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + guint i = 0; nm_assert(!priv->ready); - if (priv->num_pending_deletions == 0) { - priv->ready = TRUE; - g_signal_emit(self, signals[READY], 0); - nm_manager_unblock_failed_ovs_interfaces(nm_manager_get()); + if (priv->cleanup.num_pending_del > 0) + return; + + /* After we have deleted an interface from ovsdb, the link will stay + * in platform until ovs-vswitch removes it. To avoid race conditions, + * we need to wait until the link goes away; otherwise, after adding the + * interface again, these race conditions can happen: + * 1) we see the link in platform, and proceed with activation. But after + * that, ovs-vswitchd reads the updates from ovsdb-server and deletes/recreates + * the link. + * 2) ovs-vswitch combines the delete/insert of the interface to a no-op. NM sees + * the link staying in platform, but doesn't know whether the link is ready + * or we are again in case 1) + * In other words, it's necessary to wait that the link goes away before inserting + * the interface again. + */ + while (i < nm_g_ptr_array_len(priv->cleanup.interfaces)) { + const char *ifname; + const NMDedupMultiHeadEntry *pl_links_head_entry; + NMDedupMultiIter pliter; + const NMPlatformLink *link; + gboolean found = FALSE; + + ifname = priv->cleanup.interfaces->pdata[i]; + pl_links_head_entry = nm_platform_lookup_link_by_ifname(priv->platform, ifname); + nmp_cache_iter_for_each_link (&pliter, pl_links_head_entry, &link) { + if (link->type == NM_LINK_TYPE_OPENVSWITCH + && nmp_object_is_visible(NMP_OBJECT_UP_CAST(link))) { + found = TRUE; + break; + } + } + + if (!found) { + g_ptr_array_remove_index_fast(priv->cleanup.interfaces, i); + continue; + } + i++; } + + if (nm_g_ptr_array_len(priv->cleanup.interfaces) == 0) { + cleanup_emit_ready(self, "all interfaces deleted"); + return; + } + + _LOGT("cleanup: still waiting for %d interfaces", priv->cleanup.interfaces->len); + + if (priv->cleanup.timeout_source) { + /* We already registered the timeout/change-callback */ + return; + } + + priv->cleanup.timeout_source = + nm_g_timeout_add_seconds_source(6, G_SOURCE_FUNC(cleanup_timeout), self); + priv->cleanup.link_changed_id = g_signal_connect(priv->platform, + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK(cleanup_link_cb), + self); } static void -_del_initial_iface_cb(GError *error, gpointer user_data) +cleanup_del_iface_cb(GError *error, gpointer user_data) { NMOvsdb *self; gs_free char *ifname = NULL; @@ -2309,18 +2411,18 @@ _del_initial_iface_cb(GError *error, gpointer user_data) return; priv = NM_OVSDB_GET_PRIVATE(self); - nm_assert(priv->num_pending_deletions > 0); - priv->num_pending_deletions--; + nm_assert(priv->cleanup.num_pending_del > 0); + priv->cleanup.num_pending_del--; - _LOGD("delete initial interface '%s': %s %s%s%s, pending %u", + _LOGD("cleanup: deleted interface '%s': %s %s%s%s, pending %u", ifname, error ? "error" : "success", error ? "(" : "", error ? error->message : "", error ? ")" : "", - priv->num_pending_deletions); + priv->cleanup.num_pending_del); - _check_ready(self); + cleanup_check_ready(self); } static void @@ -2331,7 +2433,7 @@ ovsdb_cleanup_initial_interfaces(NMOvsdb *self) NMUtilsUserData *data; GHashTableIter iter; - if (priv->ready || priv->num_pending_deletions != 0) + if (priv->ready || priv->cleanup.num_pending_del > 0 || priv->cleanup.interfaces) return; /* Delete OVS interfaces added by NM. Bridges and ports and @@ -2339,17 +2441,22 @@ ovsdb_cleanup_initial_interfaces(NMOvsdb *self) * when no interface is present. */ g_hash_table_iter_init(&iter, self->_priv.interfaces); while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &interface)) { - if (interface->connection_uuid) { - priv->num_pending_deletions++; - _LOGD("deleting initial interface '%s' (pending: %u)", - interface->name, - priv->num_pending_deletions); - data = nm_utils_user_data_pack(self, g_strdup(interface->name)); - nm_ovsdb_del_interface(self, interface->name, _del_initial_iface_cb, data); + if (!interface->connection_uuid) { + /* not created by NM, ignore */ + continue; } + + if (!priv->cleanup.interfaces) + priv->cleanup.interfaces = g_ptr_array_new_with_free_func(g_free); + g_ptr_array_add(priv->cleanup.interfaces, g_strdup(interface->name)); + + _LOGD("cleanup: deleting interface '%s'", interface->name); + priv->cleanup.num_pending_del++; + data = nm_utils_user_data_pack(self, g_strdup(interface->name)); + nm_ovsdb_del_interface(self, interface->name, cleanup_del_iface_cb, data); } - _check_ready(self); + cleanup_check_ready(self); } static void @@ -2622,8 +2729,9 @@ nm_ovsdb_init(NMOvsdb *self) c_list_init(&priv->calls_lst_head); - priv->input = g_string_new(NULL); - priv->output = g_string_new(NULL); + priv->platform = g_object_ref(NM_PLATFORM_GET); + priv->input = g_string_new(NULL); + priv->output = g_string_new(NULL); priv->bridges = g_hash_table_new_full(nm_pstr_hash, nm_pstr_equal, (GDestroyNotify) _free_bridge, NULL); priv->ports = @@ -2653,6 +2761,7 @@ dispose(GObject *object) priv->output = NULL; } + g_clear_object(&priv->platform); nm_clear_pointer(&priv->bridges, g_hash_table_destroy); nm_clear_pointer(&priv->ports, g_hash_table_destroy); nm_clear_pointer(&priv->interfaces, g_hash_table_destroy); diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index e6d34266..4e073ddf 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -43,6 +43,7 @@ typedef struct { bool kill_in_progress : 1; GFileMonitor *usock_monitor; NMDeviceStageState stage1_state : 3; + GHashTable *port_configs; } NMDeviceTeamPrivate; struct _NMDeviceTeam { @@ -138,20 +139,44 @@ complete_connection(NMDevice *device, } static gboolean +_update_port_config(NMDeviceTeam *self, const char *port_iface, const char *sanitized_config) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + int err; + + err = teamdctl_port_config_update_raw(priv->tdc, port_iface, sanitized_config); + if (err != 0) { + _LOGE(LOGD_TEAM, "failed to update config for port %s (err=%d)", port_iface, err); + return FALSE; + } + + return TRUE; +} + +static gboolean ensure_teamd_connection(NMDevice *device) { NMDeviceTeam *self = NM_DEVICE_TEAM(device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); gs_free_error GError *error = NULL; + const char *port_iface; + const char *port_config; + GHashTableIter iter; if (priv->tdc) return TRUE; priv->tdc = _tdc_connect_new(self, nm_device_get_iface(device), &error); - if (!priv->tdc) + if (!priv->tdc) { _LOGE(LOGD_TEAM, "failed to connect to teamd: %s", error->message); + return FALSE; + } - return !!priv->tdc; + g_hash_table_iter_init(&iter, priv->port_configs); + while (g_hash_table_iter_next(&iter, (gpointer *) &port_iface, (gpointer *) &port_config)) + _update_port_config(self, port_iface, port_config); + + return TRUE; } static const char * @@ -840,28 +865,20 @@ attach_port(NMDevice *device, s_team_port = nm_connection_get_setting_team_port(connection); if (s_team_port) { - const char *config = nm_setting_team_port_get_config(s_team_port); - - if (config) { - if (!priv->tdc) { - _LOGW(LOGD_TEAM, - "attached team port %s config not changed, not connected to teamd", - port_iface); - } else { - gs_free char *sanitized_config = NULL; - int err; - - sanitized_config = g_strdup(config); - g_strdelimit(sanitized_config, "\r\n", ' '); - err = teamdctl_port_config_update_raw(priv->tdc, port_iface, sanitized_config); - if (err != 0) { - _LOGE(LOGD_TEAM, - "failed to update config for port %s (err=%d)", - port_iface, - err); - return FALSE; - } - } + char *sanitized_config; + + sanitized_config = g_strdup(nm_setting_team_port_get_config(s_team_port) ?: "{}"); + g_strdelimit(sanitized_config, "\r\n", ' '); + + g_hash_table_insert(priv->port_configs, g_strdup(port_iface), sanitized_config); + + if (!priv->tdc) { + _LOGW(LOGD_TEAM, + "attached team port %s config not changed, not connected to teamd", + port_iface); + } else { + if (!_update_port_config(self, port_iface, sanitized_config)) + return FALSE; } } success = nm_platform_link_enslave(nm_device_get_platform(device), @@ -885,8 +902,9 @@ attach_port(NMDevice *device, static void detach_port(NMDevice *device, NMDevice *port, gboolean configure) { - NMDeviceTeam *self = NM_DEVICE_TEAM(device); - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + NMDeviceTeam *self = NM_DEVICE_TEAM(device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + const char *port_iface = nm_device_get_ip_iface(port); gboolean do_release, success; NMSettingTeamPort *s_port; int ifindex_port; @@ -902,36 +920,36 @@ detach_port(NMDevice *device, NMDevice *port, gboolean configure) ifindex_port = nm_device_get_ip_ifindex(port); if (ifindex_port <= 0) { - _LOGD(LOGD_TEAM, "team port %s is already detached", nm_device_get_ip_iface(port)); + _LOGD(LOGD_TEAM, "team port %s is already detached", port_iface); } else if (do_release) { success = nm_platform_link_release(nm_device_get_platform(device), nm_device_get_ip_ifindex(device), ifindex_port); if (success) - _LOGI(LOGD_TEAM, "detached team port %s", nm_device_get_ip_iface(port)); + _LOGI(LOGD_TEAM, "detached team port %s", port_iface); else - _LOGW(LOGD_TEAM, "failed to detach team port %s", nm_device_get_ip_iface(port)); + _LOGW(LOGD_TEAM, "failed to detach team port %s", port_iface); /* Kernel team code "closes" the port when releasing it, (which clears * IFF_UP), so we must bring it back up here to ensure carrier changes and * other state is noticed by the now-released port. */ if (!nm_device_bring_up(port, TRUE, NULL)) { - _LOGW(LOGD_TEAM, - "detached team port %s could not be brought up", - nm_device_get_ip_iface(port)); + _LOGW(LOGD_TEAM, "detached team port %s could not be brought up", port_iface); } nm_clear_g_source(&priv->teamd_read_timeout); priv->teamd_read_timeout = g_timeout_add_seconds(5, teamd_read_timeout_cb, self); } else - _LOGI(LOGD_TEAM, "team port %s was detached", nm_device_get_ip_iface(port)); + _LOGI(LOGD_TEAM, "team port %s was detached", port_iface); /* Delete any port configuration we previously set */ if (configure && priv->tdc && (s_port = nm_device_get_applied_setting(port, NM_TYPE_SETTING_TEAM_PORT)) - && (nm_setting_team_port_get_config(s_port))) - teamdctl_port_config_update_raw(priv->tdc, nm_device_get_ip_iface(port), "{}"); + && (nm_setting_team_port_get_config(s_port))) { + _update_port_config(self, port_iface, "{}"); + g_hash_table_remove(priv->port_configs, port_iface); + } } static gboolean @@ -995,6 +1013,8 @@ constructed(GObject *object) G_OBJECT_CLASS(nm_device_team_parent_class)->constructed(object); + priv->port_configs = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free); + if (nm_dbus_manager_get_dbus_connection(nm_dbus_manager_get())) { /* Register D-Bus name watcher */ tmp_str = g_strdup_printf("org.libteam.teamd.%s", nm_device_get_ip_iface(device)); @@ -1054,6 +1074,7 @@ dispose(GObject *object) teamd_cleanup(self, TRUE); nm_clear_g_free(&priv->config); + nm_clear_pointer(&priv->port_configs, g_hash_table_destroy); G_OBJECT_CLASS(nm_device_team_parent_class)->dispose(object); } diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index c003880e..fc27c3fd 100644 --- a/src/core/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -739,7 +739,7 @@ handle_settings(GVariant *v_dict, gpointer user_data) gboolean ret = FALSE; const char *interface; const char *s; - const char **array; + gs_free const char **array = NULL; guint32 address_network, gateway_network; int ifindex; GError *error = NULL; @@ -838,15 +838,16 @@ handle_settings(GVariant *v_dict, gpointer user_data) } if (array) { gboolean any_good = FALSE; + gsize i; - for (; array[0]; array++) { - if (!nm_utils_parse_inaddr_bin(AF_INET, *array, NULL, &address_network) + for (i = 0; array[i]; i++) { + if (!nm_utils_parse_inaddr_bin(AF_INET, array[i], NULL, &address_network) || !address_network) { - _LOGW("invalid NameServer: %s", *array); + _LOGW("invalid NameServer: %s", array[i]); continue; } any_good = TRUE; - _LOGI("DNS: %s", *array); + _LOGI("DNS: %s", array[i]); nm_l3_config_data_add_nameserver(priv->l3cd_4, AF_INET, &address_network); } if (!any_good) { diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index 77cfeecf..1329b953 100644 --- a/src/core/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -115,9 +115,6 @@ typedef struct _NMDhcpClientPrivate { in_addr_t addr; NMOptionBool state; } acd; - struct { - GDBusMethodInvocation *invocation; - } bound; } v4; struct { GSource *lladdr_timeout_source; @@ -125,6 +122,8 @@ typedef struct _NMDhcpClientPrivate { } v6; }; + GDBusMethodInvocation *invocation; + struct { gulong id; bool wait_dhcp_commit : 1; @@ -909,13 +908,10 @@ _accept(NMDhcpClient *self, const NML3ConfigData *l3cd, GError **error) { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - if (!NM_IS_IPv4(priv->config.addr_family)) + if (!priv->invocation) return TRUE; - if (!priv->v4.bound.invocation) - return TRUE; - - g_dbus_method_invocation_return_value(g_steal_pointer(&priv->v4.bound.invocation), NULL); + g_dbus_method_invocation_return_value(g_steal_pointer(&priv->invocation), NULL); return TRUE; } @@ -939,20 +935,17 @@ decline(NMDhcpClient *self, const NML3ConfigData *l3cd, const char *error_messag { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - if (!NM_IS_IPv4(priv->config.addr_family)) - return TRUE; - - if (!priv->v4.bound.invocation) { + if (!priv->invocation) { nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "calling decline in unexpected script state"); return FALSE; } - - g_dbus_method_invocation_return_error(g_steal_pointer(&priv->v4.bound.invocation), + g_dbus_method_invocation_return_error(g_steal_pointer(&priv->invocation), NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, - "acd failed"); + NM_IS_IPv4(priv->config.addr_family) ? "ACD failed" + : "DAD failed"); return TRUE; } @@ -1043,8 +1036,11 @@ ipv6_lladdr_find(NMDhcpClient *self) return NULL; } -static const NMPlatformIP6Address * -ipv6_tentative_addr_find(NMDhcpClient *self) +static void +ipv6_tentative_addr_check(NMDhcpClient *self, + GPtrArray **tentative, + GPtrArray **missing, + const NMPlatformIP6Address **valid) { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); NMDedupMultiIter iter; @@ -1062,16 +1058,26 @@ ipv6_tentative_addr_find(NMDhcpClient *self) NMP_CACHE_ID_TYPE_OBJECT_TYPE, &needle)); if (!pladdr) { - /* Address was removed from platform */ + /* address removed: we assume that's because DAD failed */ + if (missing) { + if (!*missing) + *missing = g_ptr_array_new(); + g_ptr_array_add(*missing, (gpointer) addr); + } continue; } if (NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_TENTATIVE) - && !NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_OPTIMISTIC)) - return pladdr; - } + && !NM_FLAGS_HAS(pladdr->n_ifa_flags, IFA_F_OPTIMISTIC)) { + if (tentative) { + if (!*tentative) + *tentative = g_ptr_array_new(); + g_ptr_array_add(*tentative, (gpointer) addr); + } + } - return NULL; + NM_SET_OUT(valid, addr); + } } static void @@ -1108,21 +1114,61 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE && priv->l3cfg_notify.wait_ipv6_dad) { - const NMPlatformIP6Address *tentative; + gs_unref_ptrarray GPtrArray *tentative = NULL; + gs_unref_ptrarray GPtrArray *missing = NULL; + const NMPlatformIP6Address *valid = NULL; + char str[NM_UTILS_TO_STRING_BUFFER_SIZE]; + guint i; + gs_free_error GError *error = NULL; + + ipv6_tentative_addr_check(self, &tentative, &missing, &valid); + if (tentative) { + for (i = 0; i < tentative->len; i++) { + _LOGD("still waiting DAD for address: %s", + nm_platform_ip6_address_to_string(tentative->pdata[i], str, sizeof(str))); + } + } else { + /* done */ - tentative = ipv6_tentative_addr_find(self); - if (!tentative) { - _LOGD("addresses in the lease completed DAD"); priv->l3cfg_notify.wait_ipv6_dad = FALSE; nm_clear_g_source_inst(&priv->v6.dad_timeout_source); l3_cfg_notify_check_connected(self); - _emit_notify( - self, - &((NMDhcpClientNotifyData){.notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, - .lease_update = { - .l3cd = priv->l3cd_curr, - .accepted = TRUE, - }})); + + if (missing) { + for (i = 0; i < missing->len; i++) { + _LOGE("DAD failed for address: %s", + nm_platform_ip6_address_to_string(missing->pdata[i], str, sizeof(str))); + } + } + + if (valid) { + /* at least one non-duplicate address */ + _LOGD("addresses in the lease completed DAD: accept the lease"); + + if (_dhcp_client_accept(self, priv->l3cd_curr, &error)) { + _emit_notify(self, + &((NMDhcpClientNotifyData){ + .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, + .lease_update = { + .l3cd = priv->l3cd_curr, + .accepted = TRUE, + }})); + } else { + gs_free char *reason = + g_strdup_printf("error accepting lease: %s", error->message); + + _LOGD("accept failed: %s", error->message); + _emit_notify(self, + &((NMDhcpClientNotifyData){ + .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, + .it_looks_bad.reason = reason, + })); + } + } else { + _LOGD("decline the lease"); + if (!_dhcp_client_decline(self, priv->l3cd_curr, "DAD failed", &error)) + _LOGD("decline failed: %s", error->message); + } } } @@ -1155,20 +1201,23 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp address4->peer_address)) goto wait_dhcp_commit_done; } else { - const NMPlatformIP6Address *address6 = (const NMPlatformIP6Address *) lease_address; - const NMPlatformIP6Address *tentative; - char str[NM_UTILS_TO_STRING_BUFFER_SIZE]; + const NMPlatformIP6Address *address6 = (const NMPlatformIP6Address *) lease_address; + gs_unref_ptrarray GPtrArray *tentative = NULL; + char str[NM_UTILS_TO_STRING_BUFFER_SIZE]; + guint i; if (!nm_l3_config_data_lookup_address_6(committed_l3cd, &address6->address)) goto wait_dhcp_commit_done; - tentative = ipv6_tentative_addr_find(self); + ipv6_tentative_addr_check(self, &tentative, NULL, NULL); if (tentative) { priv->l3cfg_notify.wait_ipv6_dad = TRUE; priv->v6.dad_timeout_source = nm_g_timeout_add_seconds_source(30, ipv6_dad_timeout, self); - _LOGD("wait DAD for address %s", - nm_platform_ip6_address_to_string(tentative, str, sizeof(str))); + for (i = 0; i < tentative->len; i++) { + _LOGD("wait DAD for address %s", + nm_platform_ip6_address_to_string(tentative->pdata[i], str, sizeof(str))); + } } else { priv->l3cfg_notify.wait_ipv6_dad = FALSE; nm_clear_g_source_inst(&priv->v6.dad_timeout_source); @@ -1179,22 +1228,22 @@ l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDhcp l3_cfg_notify_check_connected(self); - _LOGD("accept lease"); + if (priv->config.addr_family == AF_INET || !priv->l3cfg_notify.wait_ipv6_dad) { + _LOGD("accept lease"); - if (!_dhcp_client_accept(self, priv->l3cd_curr, &error)) { - gs_free char *reason = g_strdup_printf("error accepting lease: %s", error->message); + if (!_dhcp_client_accept(self, priv->l3cd_curr, &error)) { + gs_free char *reason = g_strdup_printf("error accepting lease: %s", error->message); - _LOGD("accept failed: %s", error->message); + _LOGD("accept failed: %s", error->message); - _emit_notify(self, - &((NMDhcpClientNotifyData){ - .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, - .it_looks_bad.reason = reason, - })); - goto wait_dhcp_commit_done; - } + _emit_notify(self, + &((NMDhcpClientNotifyData){ + .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD, + .it_looks_bad.reason = reason, + })); + goto wait_dhcp_commit_done; + } - if (priv->config.addr_family == AF_INET || !priv->l3cfg_notify.wait_ipv6_dad) { _emit_notify( self, &((NMDhcpClientNotifyData){.notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE, @@ -1368,8 +1417,8 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release) priv->is_stopped = TRUE; - if (NM_IS_IPv4(priv->config.addr_family) && priv->v4.bound.invocation) { - g_dbus_method_invocation_return_error(g_steal_pointer(&priv->v4.bound.invocation), + if (priv->invocation) { + g_dbus_method_invocation_return_error(g_steal_pointer(&priv->invocation), NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "dhcp stopping"); @@ -1528,7 +1577,6 @@ nm_dhcp_client_handle_event(gpointer unused, NMPlatformIP6Address prefix = { 0, }; - int IS_IPv4; g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); g_return_val_if_fail(iface != NULL, FALSE); @@ -1625,16 +1673,13 @@ nm_dhcp_client_handle_event(gpointer unused, client_event_type = NM_DHCP_CLIENT_EVENT_TYPE_FAIL; } - IS_IPv4 = NM_IS_IPv4(priv->config.addr_family); - - if (IS_IPv4 && priv->v4.bound.invocation) - g_dbus_method_invocation_return_value(g_steal_pointer(&priv->v4.bound.invocation), NULL); + if (priv->invocation) + g_dbus_method_invocation_return_value(g_steal_pointer(&priv->invocation), NULL); - if (IS_IPv4 - && NM_IN_SET(client_event_type, - NM_DHCP_CLIENT_EVENT_TYPE_BOUND, - NM_DHCP_CLIENT_EVENT_TYPE_EXTENDED)) - priv->v4.bound.invocation = g_steal_pointer(&invocation); + if (NM_IN_SET(client_event_type, + NM_DHCP_CLIENT_EVENT_TYPE_BOUND, + NM_DHCP_CLIENT_EVENT_TYPE_EXTENDED)) + priv->invocation = g_steal_pointer(&invocation); _nm_dhcp_client_notify(self, client_event_type, l3cd); @@ -1785,10 +1830,6 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps * explicitly initialize the respective union member. */ if (NM_IS_IPv4(priv->config.addr_family)) { priv->v4 = (typeof(priv->v4)){ - .bound = - { - .invocation = NULL, - }, .acd = { .addr = INADDR_ANY, diff --git a/src/core/dhcp/nm-dhcp-helper.c b/src/core/dhcp/nm-dhcp-helper.c index 5a17f4e8..78db617c 100644 --- a/src/core/dhcp/nm-dhcp-helper.c +++ b/src/core/dhcp/nm-dhcp-helper.c @@ -114,6 +114,8 @@ main(int argc, char *argv[]) gint64 time_start; gint64 time_end; gint64 remaining_time; + gboolean IS_IPv4; + const char *reason; /* Connecting to the unix socket can fail with EAGAIN if there are too * many pending connections and the server can't accept them in time @@ -124,7 +126,19 @@ main(int argc, char *argv[]) time_end = time_start + (5000 * 1000L); try_count = 0; - _LOGi("nm-dhcp-helper: event called"); + reason = getenv("reason"); + + _LOGi("nm-dhcp-helper: event called: %s", reason); + + IS_IPv4 = !NM_IN_STRSET(reason, + "PREINIT6", + "BOUND6", + "RENEW6", + "REBIND6", + "DEPREF6", + "EXPIRE6", + "RELEASE6", + "STOP6"); do_connect: try_count++; @@ -244,5 +258,6 @@ out: } _LOGi("success: %s", success ? "YES" : "NO"); - return success ? EXIT_SUCCESS : EXIT_FAILURE; + /* The error code to send a decline depends on the address family */ + return success ? EXIT_SUCCESS : (IS_IPv4 ? 1 : 3); } diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index 1e54452a..a2fead3f 100644 --- a/src/core/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -2039,8 +2039,15 @@ nm_dns_manager_set_ip_config(NMDnsManager *self, if (!ip_data) { ip_data = _dns_config_ip_data_new(data, addr_family, source_tag, l3cd, ip_config_type); - if (!any_removed) + priv->ip_data_lst_need_sort = TRUE; + if (!any_removed) { + /* `any_removed` tracks whether we deleted any ip_data. If that happened, + * we already compared the old and new l3cds and set `changed` accordingly. + * Here we only need to set `changed` if we are adding a new ip_data without + * removing the old one. + */ changed = TRUE; + } } else { ip_data->ip_config_type = ip_config_type; changed = TRUE; diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c index 0f512e38..753e3fb5 100644 --- a/src/core/nm-config-data.c +++ b/src/core/nm-config-data.c @@ -585,7 +585,7 @@ _merge_keyfiles(GKeyFile *keyfile_user, GKeyFile *keyfile_intern) if (!keys) continue; - is_intern = g_str_has_prefix(group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + is_intern = NM_STR_HAS_PREFIX(group, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); if (!is_intern && g_key_file_has_key(keyfile_intern, group, @@ -634,9 +634,11 @@ _nm_config_data_log_sort(const char **pa, const char **pb, gpointer dummy) const char *a = *pa; const char *b = *pb; + nm_assert(a && b && !nm_streq(a, b)); + /* we sort intern groups to the end. */ - a_is_intern = g_str_has_prefix(a, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); - b_is_intern = g_str_has_prefix(b, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + a_is_intern = NM_STR_HAS_PREFIX(a, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); + b_is_intern = NM_STR_HAS_PREFIX(b, NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN); if (a_is_intern && b_is_intern) return 0; @@ -646,8 +648,8 @@ _nm_config_data_log_sort(const char **pa, const char **pb, gpointer dummy) return -1; /* we sort connection groups before intern groups (to the end). */ - a_is_connection = a && g_str_has_prefix(a, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); - b_is_connection = b && g_str_has_prefix(b, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); + a_is_connection = NM_STR_HAS_PREFIX(a, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); + b_is_connection = NM_STR_HAS_PREFIX(b, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION); if (a_is_connection && b_is_connection) { /* if both are connection groups, we want the explicit [connection] group first. */ @@ -668,8 +670,8 @@ _nm_config_data_log_sort(const char **pa, const char **pb, gpointer dummy) return -1; /* we sort device groups before connection groups (to the end). */ - a_is_device = a && g_str_has_prefix(a, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE); - b_is_device = b && g_str_has_prefix(b, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE); + a_is_device = NM_STR_HAS_PREFIX(a, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE); + b_is_device = NM_STR_HAS_PREFIX(b, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE); if (a_is_device && b_is_device) { /* if both are device groups, we want the explicit [device] group first. */ @@ -770,27 +772,48 @@ nm_config_data_log(const NMConfigData *self, groups_full = g_ptr_array_sized_new(ngroups + 5); if (ngroups) { + /* g_key_file_get_groups() can return duplicates ( :( ), but the + * keyfile that we constructed should not have any. Assert for that. */ + nm_assert(!nm_strv_has_duplicate((const char *const *) groups, ngroups, FALSE)); + g_ptr_array_set_size(groups_full, ngroups); memcpy(groups_full->pdata, groups, sizeof(groups[0]) * ngroups); - g_ptr_array_sort_with_data(groups_full, (GCompareDataFunc) _nm_config_data_log_sort, NULL); } if (print_default) { for (g = 0; g < G_N_ELEMENTS(default_values); g++) { const char *group = default_values[g].group; - gssize idx; + guint g2; - idx = nm_utils_array_find_binary_search((gconstpointer *) groups_full->pdata, - sizeof(char *), - groups_full->len, - &group, - (GCompareDataFunc) _nm_config_data_log_sort, - NULL); - if (idx < 0) - g_ptr_array_insert(groups_full, (~idx), (gpointer) group); + if (g > 0) { + if (nm_streq(group, default_values[g - 1].group)) { + /* Repeated values. We already added this one. Skip */ + continue; + } + if (NM_MORE_ASSERT_ONCE(20)) { + /* We require that the default values are grouped by their "group". + * That is, all default values for a certain "group" are close to + * each other in the list. Assert for that. */ + for (g2 = g + 1; g2 < groups_full->len; g2++) { + nm_assert(!nm_streq(default_values[g - 1].group, default_values[g2].group)); + } + } + } + + for (g2 = 0; g2 < groups_full->len; g2++) { + if (nm_streq(group, groups_full->pdata[g2])) + goto next; + } + + g_ptr_array_add(groups_full, (gpointer) group); + +next: + (void) 0; } } + g_ptr_array_sort_with_data(groups_full, (GCompareDataFunc) _nm_config_data_log_sort, NULL); + if (!stream) _LOG(stream, prefix, "config-data[%p]: %u groups", self, groups_full->len); diff --git a/src/core/nm-connectivity.c b/src/core/nm-connectivity.c index 25ac3c7f..cd30853d 100644 --- a/src/core/nm-connectivity.c +++ b/src/core/nm-connectivity.c @@ -82,7 +82,6 @@ struct _NMConnectivityCheckHandle { gsize response_good_cnt; guint curl_timer; - int ch_ifindex; } concheck; #endif @@ -1049,8 +1048,6 @@ nm_connectivity_check_start(NMConnectivity *self, NMConnectivityState state; const char *reason; - cb_data->concheck.ch_ifindex = ifindex; - if (platform) { state = check_platform_config(self, platform, ifindex, addr_family, &reason); nm_assert((state == NM_CONNECTIVITY_UNKNOWN) == !reason); @@ -1106,7 +1103,7 @@ nm_connectivity_check_start(NMConnectivity *self, "org.freedesktop.resolve1.Manager", "ResolveHostname", g_variant_new("(isit)", - (gint32) cb_data->concheck.ch_ifindex, + 0, cb_data->concheck.con_config->host, (gint32) cb_data->addr_family, SD_RESOLVED_DNS), diff --git a/src/core/nm-firewall-utils.c b/src/core/nm-firewall-utils.c index 1311f503..e482ab96 100644 --- a/src/core/nm-firewall-utils.c +++ b/src/core/nm-firewall-utils.c @@ -111,6 +111,8 @@ _share_iptables_get_name(gboolean is_iptables_chain, const char *prefix, const c return nm_str_buf_finalize(&strbuf, NULL); } +/*****************************************************************************/ + static gboolean _share_iptables_call_v(const char *const *argv) { @@ -171,7 +173,7 @@ _share_iptables_chain_add(const char *table, const char *chain) } static void -_share_iptables_set_masquerade(gboolean add, const char *ip_iface, in_addr_t addr, guint8 plen) +_share_iptables_set_masquerade_sync(gboolean up, const char *ip_iface, in_addr_t addr, guint8 plen) { char str_subnet[_SHARE_IPTABLES_SUBNET_TO_STR_LEN]; gs_free char *comment_name = NULL; @@ -182,7 +184,7 @@ _share_iptables_set_masquerade(gboolean add, const char *ip_iface, in_addr_t add _share_iptables_call("" IPTABLES_PATH "", "--table", "nat", - add ? "--insert" : "--delete", + up ? "--insert" : "--delete", "POSTROUTING", "--source", str_subnet, @@ -309,8 +311,8 @@ _share_iptables_set_shared_chains_delete(const char *chain_input, const char *ch _share_iptables_chain_delete("filter", chain_forward); } -_nm_unused static void -_share_iptables_set_shared(gboolean add, const char *ip_iface, in_addr_t addr, guint plen) +static void +_share_iptables_set_shared_sync(gboolean up, const char *ip_iface, in_addr_t addr, guint plen) { gs_free char *comment_name = NULL; gs_free char *chain_input = NULL; @@ -320,13 +322,13 @@ _share_iptables_set_shared(gboolean add, const char *ip_iface, in_addr_t addr, g chain_input = _share_iptables_get_name(TRUE, "nm-sh-in", ip_iface); chain_forward = _share_iptables_get_name(TRUE, "nm-sh-fw", ip_iface); - if (add) + if (up) _share_iptables_set_shared_chains_add(chain_input, chain_forward, ip_iface, addr, plen); _share_iptables_call("" IPTABLES_PATH "", "--table", "filter", - add ? "--insert" : "--delete", + up ? "--insert" : "--delete", "INPUT", "--in-interface", ip_iface, @@ -340,7 +342,7 @@ _share_iptables_set_shared(gboolean add, const char *ip_iface, in_addr_t addr, g _share_iptables_call("" IPTABLES_PATH "", "--table", "filter", - add ? "--insert" : "--delete", + up ? "--insert" : "--delete", "FORWARD", "--jump", chain_forward, @@ -349,7 +351,7 @@ _share_iptables_set_shared(gboolean add, const char *ip_iface, in_addr_t addr, g "--comment", comment_name); - if (!add) + if (!up) _share_iptables_set_shared_chains_delete(chain_input, chain_forward); } @@ -428,14 +430,21 @@ _fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user } else if (g_subprocess_get_successful(call_data->subprocess)) { nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: command successful", call_data->identifier); } else { + char buf[NM_UTILS_GET_PROCESS_EXIT_STATUS_BUF_LEN]; gs_free char *ss_stdout = NULL; gs_free char *ss_stderr = NULL; gboolean print_stdout = (stdout_buf && g_bytes_get_size(stdout_buf) > 0); gboolean print_stderr = (stderr_buf && g_bytes_get_size(stderr_buf) > 0); + int status; + + status = g_subprocess_get_status(call_data->subprocess); + + nm_utils_get_process_exit_status_desc_buf(status, buf, sizeof(buf)); nm_log_warn(LOGD_SHARING, - "firewall: nft[%s]: command failed:%s%s%s%s%s%s%s", + "firewall: nft[%s]: command %s:%s%s%s%s%s%s%s", call_data->identifier, + buf, print_stdout || print_stderr ? "" : " unknown reason", NM_PRINT_FMT_QUOTED( print_stdout, @@ -453,6 +462,8 @@ _fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user &ss_stderr), "\")", "")); + + nm_utils_error_set(&error, NM_UTILS_ERROR_COMMAND_FAILED, "nft command %s", buf); } _fw_nft_call_data_free(call_data, g_steal_pointer(&error)); @@ -486,23 +497,31 @@ _fw_nft_call_timeout_cb(gpointer user_data) return G_SOURCE_CONTINUE; } -static void -_fw_nft_call(GBytes *stdin_buf, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer callback_user_data) +void +nm_firewall_nft_call(GBytes *stdin_buf, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer callback_user_data) { gs_unref_object GSubprocessLauncher *subprocess_launcher = NULL; gs_free_error GError *error = NULL; FwNftCallData *call_data; + gs_free char *ss1 = NULL; call_data = g_slice_new(FwNftCallData); *call_data = (FwNftCallData){ - .task = nm_g_task_new(NULL, cancellable, _fw_nft_call, callback, callback_user_data), - .subprocess = NULL, + .task = + nm_g_task_new(NULL, cancellable, nm_firewall_nft_call, callback, callback_user_data), + .subprocess = NULL, .timeout_source = NULL, }; + nm_log_trace(LOGD_SHARING, + "firewall: nft: call command: [ '%s' ]", + nm_utils_buf_utf8safe_escape_bytes(stdin_buf, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, + &ss1)); + if (cancellable) { call_data->cancellable_id = g_cancellable_connect(cancellable, G_CALLBACK(_fw_nft_call_cancelled_cb), @@ -554,10 +573,10 @@ _fw_nft_call(GBytes *stdin_buf, g_task_get_context(call_data->task)); } -static gboolean -_fw_nft_call_finish(GAsyncResult *result, GError **error) +gboolean +nm_firewall_nft_call_finish(GAsyncResult *result, GError **error) { - g_return_val_if_fail(nm_g_task_is_valid(result, NULL, _fw_nft_call), FALSE); + g_return_val_if_fail(nm_g_task_is_valid(result, NULL, nm_firewall_nft_call), FALSE); return g_task_propagate_boolean(G_TASK(result), error); } @@ -575,7 +594,7 @@ _fw_nft_call_sync_done(GObject *source, GAsyncResult *result, gpointer user_data { FwNftCallSyncData *data = user_data; - data->success = _fw_nft_call_finish(result, data->error); + data->success = nm_firewall_nft_call_finish(result, data->error); g_main_loop_quit(data->loop); } @@ -590,7 +609,7 @@ _fw_nft_call_sync(GBytes *stdin_buf, GError **error) .error = error, }; - _fw_nft_call(stdin_buf, NULL, _fw_nft_call_sync_done, &data); + nm_firewall_nft_call(stdin_buf, NULL, _fw_nft_call_sync_done, &data); g_main_loop_run(main_loop); return data.success; @@ -598,25 +617,30 @@ _fw_nft_call_sync(GBytes *stdin_buf, GError **error) /*****************************************************************************/ +#define _append(p_strbuf, fmt, ...) nm_str_buf_append_printf((p_strbuf), "" fmt "\n", ##__VA_ARGS__) + static void -_fw_nft_set(gboolean add, const char *ip_iface, in_addr_t addr, guint8 plen) +_fw_nft_append_cmd_table(NMStrBuf *strbuf, const char *family, const char *table_name, gboolean up) +{ + /* Either delete the table, or create/flush it. */ + _append(strbuf, "add table %s %s", family, table_name); + _append(strbuf, "%s table %s %s", up ? "flush" : "delete", family, table_name); +} + +static GBytes * +_fw_nft_set_shared_construct(gboolean up, const char *ip_iface, in_addr_t addr, guint8 plen) { nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE); - gs_unref_bytes GBytes *stdin_buf = NULL; gs_free char *table_name = NULL; - gs_free char *ss1 = NULL; char str_subnet[_SHARE_IPTABLES_SUBNET_TO_STR_LEN]; table_name = _share_iptables_get_name(FALSE, "nm-shared", ip_iface); _share_iptables_subnet_to_str(str_subnet, addr, plen); -#define _append(p_strbuf, fmt, ...) nm_str_buf_append_printf((p_strbuf), "" fmt "\n", ##__VA_ARGS__) - - _append(&strbuf, "add table ip %s", table_name); - _append(&strbuf, "%s table ip %s", add ? "flush" : "delete", table_name); + _fw_nft_append_cmd_table(&strbuf, "ip", table_name, up); - if (add) { + if (up) { _append(&strbuf, "add chain ip %s nat_postrouting {" " type nat hook postrouting priority 100; policy accept; " @@ -631,16 +655,15 @@ _fw_nft_set(gboolean add, const char *ip_iface, in_addr_t addr, guint8 plen) /* This filter_input chain serves no real purpose, because "accept" only stops * evaluation of the current rule. It cannot fully accept the packet. Since * this chain has no other rules, it is useless in this form. + * + * _append(&strbuf, + * "add chain ip %s filter_input {" + * " type filter hook input priority 0; policy accept; " + * "};", + * table_name); + * _append(&strbuf, "add rule ip %s filter_input tcp dport { 67, 53 } accept;", table_name); + * _append(&strbuf, "add rule ip %s filter_input udp dport { 67, 53 } accept;", table_name); */ - /* - _append(&strbuf, - "add chain ip %s filter_input {" - " type filter hook input priority 0; policy accept; " - "};", - table_name); - _append(&strbuf, "add rule ip %s filter_input tcp dport { 67, 53 } accept;", table_name); - _append(&strbuf, "add rule ip %s filter_input udp dport { 67, 53 } accept;", table_name); - */ _append(&strbuf, "add chain ip %s filter_forward {" @@ -673,14 +696,7 @@ _fw_nft_set(gboolean add, const char *ip_iface, in_addr_t addr, guint8 plen) ip_iface); } - nm_log_trace(LOGD_SHARING, - "firewall: nft command: [ %s ]", - nm_utils_str_utf8safe_escape(nm_str_buf_get_str(&strbuf), - NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, - &ss1)); - - stdin_buf = nm_str_buf_finalize_to_gbytes(&strbuf); - _fw_nft_call_sync(stdin_buf, NULL); + return nm_str_buf_finalize_to_gbytes(&strbuf); } /*****************************************************************************/ @@ -692,7 +708,7 @@ struct _NMFirewallConfig { }; NMFirewallConfig * -nm_firewall_config_new(const char *ip_iface, in_addr_t addr, guint8 plen) +nm_firewall_config_new_shared(const char *ip_iface, in_addr_t addr, guint8 plen) { NMFirewallConfig *self; @@ -719,17 +735,24 @@ nm_firewall_config_free(NMFirewallConfig *self) nm_g_slice_free(self); } +/*****************************************************************************/ + void -nm_firewall_config_apply(NMFirewallConfig *self, gboolean shared) +nm_firewall_config_apply_sync(NMFirewallConfig *self, gboolean up) { switch (nm_firewall_utils_get_backend()) { case NM_FIREWALL_BACKEND_IPTABLES: - _share_iptables_set_masquerade(shared, self->ip_iface, self->addr, self->plen); - _share_iptables_set_shared(shared, self->ip_iface, self->addr, self->plen); + _share_iptables_set_masquerade_sync(up, self->ip_iface, self->addr, self->plen); + _share_iptables_set_shared_sync(up, self->ip_iface, self->addr, self->plen); break; case NM_FIREWALL_BACKEND_NFTABLES: - _fw_nft_set(shared, self->ip_iface, self->addr, self->plen); + { + gs_unref_bytes GBytes *stdin_buf = NULL; + + stdin_buf = _fw_nft_set_shared_construct(up, self->ip_iface, self->addr, self->plen); + _fw_nft_call_sync(stdin_buf, NULL); break; + } case NM_FIREWALL_BACKEND_NONE: break; default: diff --git a/src/core/nm-firewall-utils.h b/src/core/nm-firewall-utils.h index 3d6c8a69..9d883fea 100644 --- a/src/core/nm-firewall-utils.h +++ b/src/core/nm-firewall-utils.h @@ -20,10 +20,19 @@ NMFirewallBackend nm_firewall_utils_get_backend(void); typedef struct _NMFirewallConfig NMFirewallConfig; -NMFirewallConfig *nm_firewall_config_new(const char *ip_iface, in_addr_t addr, guint8 plen); +NMFirewallConfig *nm_firewall_config_new_shared(const char *ip_iface, in_addr_t addr, guint8 plen); void nm_firewall_config_free(NMFirewallConfig *self); -void nm_firewall_config_apply(NMFirewallConfig *self, gboolean shared); +void nm_firewall_config_apply_sync(NMFirewallConfig *self, gboolean up); + +/*****************************************************************************/ + +void nm_firewall_nft_call(GBytes *stdin_buf, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer callback_user_data); + +gboolean nm_firewall_nft_call_finish(GAsyncResult *result, GError **error); #endif /* __NM_FIREWALL_UTILS_H__ */ diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index 69ea0d26..8fa1e07d 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -4010,7 +4010,7 @@ _l3_commit_ndisc_params(NML3Cfg *self, NML3CfgCommitType commit_type) if (retrans_set && (!self->priv.p->ndisc_retrans_timer_msec_set - || self->priv.p->ndisc_reachable_time_msec != retrans)) { + || self->priv.p->ndisc_retrans_timer_msec != retrans)) { self->priv.p->ndisc_retrans_timer_msec = retrans; self->priv.p->ndisc_retrans_timer_msec_set = TRUE; if (ifname) { diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index 16b0211f..518fc596 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -797,6 +797,20 @@ device_dns_lookup_done(NMDevice *device, gpointer user_data) } static void +device_carrier_changed(NMDevice *device, GParamSpec *pspec, gpointer user_data) +{ + NMPolicyPrivate *priv = user_data; + NMPolicy *self = _PRIV_TO_SELF(priv); + gs_free char *msg = NULL; + + if (nm_device_has_carrier(device)) { + g_signal_handlers_disconnect_by_func(device, device_carrier_changed, priv); + msg = g_strdup_printf("device '%s' got carrier", nm_device_get_iface(device)); + update_system_hostname(self, msg); + } +} + +static void update_system_hostname(NMPolicy *self, const char *msg) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); @@ -880,6 +894,7 @@ update_system_hostname(NMPolicy *self, const char *msg) info = &g_array_index(infos, DeviceHostnameInfo, i); addr_family = info->IS_IPv4 ? AF_INET : AF_INET6; g_signal_handlers_disconnect_by_func(info->device, device_dns_lookup_done, self); + g_signal_handlers_disconnect_by_func(info->device, device_carrier_changed, priv); if (info->from_dhcp) { dhcp_config = nm_device_get_dhcp_config(info->device, addr_family); @@ -905,10 +920,18 @@ update_system_hostname(NMPolicy *self, const char *msg) if (priv->hostname_mode != NM_POLICY_HOSTNAME_MODE_DHCP) { if (info->from_dns) { - const char *result; - gboolean wait = FALSE; + const char *result = NULL; + gboolean wait = FALSE; - result = nm_device_get_hostname_from_dns_lookup(info->device, addr_family, &wait); + if (nm_device_has_carrier(info->device)) { + result = + nm_device_get_hostname_from_dns_lookup(info->device, addr_family, &wait); + } else { + g_signal_connect(info->device, + "notify::" NM_DEVICE_CARRIER, + G_CALLBACK(device_carrier_changed), + priv); + } if (result) { _set_hostname(self, result, "from address lookup"); return; @@ -1556,6 +1579,7 @@ nm_policy_unblock_failed_ovs_interfaces(NMPolicy *self) NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); NMSettingsConnection *const *connections = NULL; guint i; + gboolean multiconnect = FALSE; _LOGT(LOGD_DEVICE, "unblocking failed OVS interfaces"); @@ -1563,6 +1587,13 @@ nm_policy_unblock_failed_ovs_interfaces(NMPolicy *self) for (i = 0; connections[i]; i++) { NMSettingsConnection *sett_conn = connections[i]; NMConnection *connection = nm_settings_connection_get_connection(sett_conn); + NMSettingConnection *s_con = nm_connection_get_setting_connection(connection); + + /* Check if any connection is connect multiple */ + if (s_con + && nm_setting_connection_get_multi_connect(s_con) + == NM_CONNECTION_MULTI_CONNECT_MULTIPLE) + multiconnect = TRUE; if (nm_connection_get_setting_ovs_interface(connection)) { nm_settings_connection_autoconnect_retries_reset(sett_conn); @@ -1572,6 +1603,18 @@ nm_policy_unblock_failed_ovs_interfaces(NMPolicy *self) FALSE); } } + + /* There is, at least, one multiconnect connection with an OVS setting. + * Let's check the OVS devices retries */ + if (multiconnect) { + NMDevice *device; + GHashTableIter h_iter; + g_hash_table_iter_init(&h_iter, priv->devices); + while (g_hash_table_iter_next(&h_iter, (gpointer *) &device, NULL)) { + if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_OVS_INTERFACE) + nm_device_autoconnect_retries_reset(device); + } + } } static gboolean @@ -1583,7 +1626,8 @@ reset_autoconnect_all( NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); NMSettingsConnection *const *connections = NULL; guint i; - gboolean changed = FALSE; + gboolean changed = FALSE; + gboolean multiconnect = FALSE; _LOGD(LOGD_DEVICE, "re-enabling autoconnect for all connections%s%s%s", @@ -1594,6 +1638,8 @@ reset_autoconnect_all( connections = nm_settings_get_connections(priv->settings, NULL); for (i = 0; connections[i]; i++) { NMSettingsConnection *sett_conn = connections[i]; + NMSettingConnection *s_con = + nm_connection_get_setting_connection(nm_settings_connection_get_connection(sett_conn)); if (device && !nm_device_check_connection_compatible( @@ -1602,6 +1648,11 @@ reset_autoconnect_all( NULL)) continue; + if (s_con + && nm_setting_connection_get_multi_connect(s_con) + == NM_CONNECTION_MULTI_CONNECT_MULTIPLE) + multiconnect = TRUE; + if (only_no_secrets) { /* we only reset the no-secrets blocked flag. */ if (nm_settings_connection_autoconnect_blocked_reason_set( @@ -1630,6 +1681,20 @@ reset_autoconnect_all( } } } + + /* There is, at least, one multiconnect connection. Let's check the devices retries */ + if (multiconnect) { + NMDevice *device_iter; + GHashTableIter h_iter; + g_hash_table_iter_init(&h_iter, priv->devices); + while (g_hash_table_iter_next(&h_iter, (gpointer *) &device_iter, NULL)) { + if (nm_device_get_autoconnect_retries(device_iter) != -2) { + nm_device_autoconnect_retries_reset(device_iter); + changed = TRUE; + } + } + } + return changed; } @@ -1687,7 +1752,8 @@ reset_connections_retries(gpointer user_data) NMSettingsConnection *const *connections = NULL; guint i; gint32 con_stamp, min_stamp, now; - gboolean changed = FALSE; + gboolean changed = FALSE; + gboolean multiconnect = FALSE; priv->reset_retries_id = 0; @@ -1696,6 +1762,14 @@ reset_connections_retries(gpointer user_data) connections = nm_settings_get_connections(priv->settings, NULL); for (i = 0; connections[i]; i++) { NMSettingsConnection *connection = connections[i]; + NMSettingConnection *s_con = + nm_connection_get_setting_connection(nm_settings_connection_get_connection(connection)); + + /* Check if any connection is connect multiple */ + if (s_con + && nm_setting_connection_get_multi_connect(s_con) + == NM_CONNECTION_MULTI_CONNECT_MULTIPLE) + multiconnect = TRUE; con_stamp = nm_settings_connection_autoconnect_retries_blocked_until(connection); if (con_stamp == 0) @@ -1708,6 +1782,25 @@ reset_connections_retries(gpointer user_data) min_stamp = con_stamp; } + /* There is, at least, one multiconnect connection. Let's check the devices retries */ + if (multiconnect) { + NMDevice *device; + GHashTableIter h_iter; + g_hash_table_iter_init(&h_iter, priv->devices); + while (g_hash_table_iter_next(&h_iter, (gpointer *) &device, NULL)) { + con_stamp = nm_device_autoconnect_retries_blocked_until(device); + + /* default value in device is -2, which means, we do not care */ + if (con_stamp <= 0) + continue; + if (con_stamp <= now) { + nm_device_autoconnect_retries_reset(device); + changed = TRUE; + } else if (min_stamp == 0 || min_stamp > con_stamp) + min_stamp = con_stamp; + } + } + /* Schedule the handler again if there are some stamps left */ if (min_stamp != 0) priv->reset_retries_id = @@ -1721,21 +1814,31 @@ reset_connections_retries(gpointer user_data) } static void -_connection_autoconnect_retries_set(NMPolicy *self, NMSettingsConnection *connection, int tries) +_connection_autoconnect_retries_set(NMPolicy *self, + NMSettingsConnection *connection, + NMDevice *device, + int tries) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); + NMSettingConnection *s_con; + gint32 retry_time; nm_assert(NM_IS_SETTINGS_CONNECTION(connection)); nm_assert(tries >= 0); - nm_settings_connection_autoconnect_retries_set(connection, tries); + s_con = nm_connection_get_setting_connection(nm_settings_connection_get_connection(connection)); + if (s_con + && nm_setting_connection_get_multi_connect(s_con) == NM_CONNECTION_MULTI_CONNECT_MULTIPLE) { + nm_device_set_autoconnect_retries(device, tries); + retry_time = nm_device_autoconnect_retries_blocked_until(device); + } else { + nm_settings_connection_autoconnect_retries_set(connection, tries); + retry_time = nm_settings_connection_autoconnect_retries_blocked_until(connection); + } if (tries == 0) { /* Schedule a handler to reset retries count */ if (!priv->reset_retries_id) { - gint32 retry_time = - nm_settings_connection_autoconnect_retries_blocked_until(connection); - g_warn_if_fail(retry_time != 0); priv->reset_retries_id = g_timeout_add_seconds(MAX(0, retry_time - nm_utils_get_monotonic_timestamp_sec()), @@ -1997,13 +2100,25 @@ device_state_changed(NMDevice *device, } if (!blocked) { - tries = nm_settings_connection_autoconnect_retries_get(sett_conn); + s_con = nm_connection_get_setting_connection( + nm_settings_connection_get_connection(sett_conn)); + if (s_con + && nm_setting_connection_get_multi_connect(s_con) + == NM_CONNECTION_MULTI_CONNECT_MULTIPLE) { + if (nm_device_get_autoconnect_retries(device) == -2) + nm_device_set_autoconnect_retries( + device, + nm_settings_connection_autoconnect_retries_get(sett_conn)); + + tries = nm_device_get_autoconnect_retries(device); + } else + tries = nm_settings_connection_autoconnect_retries_get(sett_conn); if (tries > 0) { _LOGD(LOGD_DEVICE, "connection '%s' failed to autoconnect; %d tries left", nm_settings_connection_get_id(sett_conn), tries - 1); - _connection_autoconnect_retries_set(self, sett_conn, tries - 1); + _connection_autoconnect_retries_set(self, sett_conn, device, tries - 1); } else if (tries != 0) { _LOGD(LOGD_DEVICE, "connection '%s' failed to autoconnect; infinite tries left", @@ -2893,7 +3008,7 @@ dispose(GObject *object) } g_hash_table_iter_init(&h_iter, priv->devices); - if (g_hash_table_iter_next(&h_iter, (gpointer *) &device, NULL)) { + while (g_hash_table_iter_next(&h_iter, (gpointer *) &device, NULL)) { g_hash_table_iter_remove(&h_iter); devices_list_unregister(self, device); } diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 6452d72a..4d8e7bd6 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -5355,59 +5355,41 @@ wired_connection_from_ifcfg(const char *file, shvarFile *ifcfg, GError **error) static gboolean parse_infiniband_p_key(shvarFile *ifcfg, int *out_p_key, char **out_parent, GError **error) { - char *device = NULL, *physdev = NULL, *pkey_id = NULL; - char *ifname = NULL; - int id; - gboolean ret = FALSE; - - device = svGetValueStr_cp(ifcfg, "DEVICE"); - if (!device) { - PARSE_WARNING("InfiniBand connection specified PKEY but not DEVICE"); - goto done; - } + gs_free char *physdev = NULL; + gs_free char *pkey_id = NULL; + int id; physdev = svGetValueStr_cp(ifcfg, "PHYSDEV"); if (!physdev) { - PARSE_WARNING("InfiniBand connection specified PKEY but not PHYSDEV"); - goto done; + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "infiniband connection specified PKEY but not PHYSDEV"); + return FALSE; } pkey_id = svGetValueStr_cp(ifcfg, "PKEY_ID"); if (!pkey_id) { - PARSE_WARNING("InfiniBand connection specified PKEY but not PKEY_ID"); - goto done; + g_set_error(error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "infiniband connection specified PKEY but not PKEY_ID"); + return FALSE; } id = _nm_utils_ascii_str_to_int64(pkey_id, 0, 0, 0xFFFF, -1); if (id == -1) { - PARSE_WARNING("invalid InfiniBand PKEY_ID '%s'", pkey_id); - goto done; - } - id = (id | 0x8000); - - ifname = g_strdup_printf("%s.%04x", physdev, (unsigned) id); - if (strcmp(device, ifname) != 0) { - PARSE_WARNING("InfiniBand DEVICE (%s) does not match PHYSDEV+PKEY_ID (%s)", device, ifname); - goto done; - } - - *out_p_key = id; - *out_parent = g_strdup(physdev); - ret = TRUE; - -done: - g_free(device); - g_free(physdev); - g_free(pkey_id); - g_free(ifname); - - if (!ret) { g_set_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to create InfiniBand setting"); + "invalid infiniband PKEY_ID '%s'", + pkey_id); + return FALSE; } - return ret; + + *out_p_key = id; + *out_parent = g_steal_pointer(&physdev); + return TRUE; } static NMSetting * diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 96efc9e5..e8948c3d 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1312,6 +1312,7 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error gboolean is_first; guint32 u32; gboolean b; + gboolean any_option = FALSE; s_con = nm_connection_get_setting_connection(connection); if (s_con) { @@ -1341,6 +1342,7 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error g_string_append_c(str, ' '); g_string_append(str, nms_ifcfg_rh_utils_get_ethtool_name(ethtool_id)); g_string_append(str, b ? " on" : " off"); + any_option = TRUE; } is_first = TRUE; @@ -1356,6 +1358,7 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error g_string_append_c(str, ' '); g_string_append(str, nms_ifcfg_rh_utils_get_ethtool_name(ethtool_id)); g_string_append_printf(str, " %" G_GUINT32_FORMAT, u32); + any_option = TRUE; } is_first = TRUE; @@ -1371,7 +1374,10 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error g_string_append_c(str, ' '); g_string_append(str, nms_ifcfg_rh_utils_get_ethtool_name(ethtool_id)); g_string_append_printf(str, " %" G_GUINT32_FORMAT, u32); + any_option = TRUE; } + + is_first = TRUE; for (ethtool_id = _NM_ETHTOOL_ID_PAUSE_FIRST; ethtool_id <= _NM_ETHTOOL_ID_PAUSE_LAST; ethtool_id++) { nm_assert(nms_ifcfg_rh_utils_get_ethtool_name(ethtool_id)); @@ -1384,9 +1390,10 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error g_string_append_c(str, ' '); g_string_append(str, nms_ifcfg_rh_utils_get_ethtool_name(ethtool_id)); g_string_append(str, b ? " on" : " off"); + any_option = TRUE; } - if (!str) { + if (!any_option) { /* Write an empty dummy "-A" option without arguments. This is to * ensure that the reader will create an (all default) NMSettingEthtool. * Also, it seems that `ethtool -A "$IFACE"` is silently accepted. */ diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ipoib b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ipoib new file mode 100644 index 00000000..b45da5f7 --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ipoib @@ -0,0 +1,9 @@ +TYPE=InfiniBand +PKEY=yes +PKEY_ID=12 +PHYSDEV=ib0 +CONNECTED_MODE=yes +IPADDR=192.168.2.2 +NETMASK=255.255.255.0 +GATEWAY=192.168.2.1 +NAME=ib012 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-6.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-6.cexpected new file mode 100644 index 00000000..784ad224 --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-6.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg on ; -A net0 pause-autoneg off" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=default +NAME=test_roundtrip_ethtool +UUID=${UUID} +ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-7.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-7.cexpected new file mode 100644 index 00000000..02ab14fe --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-7.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg on ; -G net0 rx 512" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=default +NAME=test_roundtrip_ethtool +UUID=${UUID} +ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-8.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-8.cexpected new file mode 100644 index 00000000..fd760839 --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-8.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg on ; -A net0" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=default +NAME=test_roundtrip_ethtool +UUID=${UUID} +ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-9.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-9.cexpected new file mode 100644 index 00000000..1703b0dc --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_roundtrip_ethtool-9.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg on ; -G net0 rx 512 ; -A net0 pause-autoneg off" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=default +NAME=test_roundtrip_ethtool +UUID=${UUID} +ONBOOT=yes diff --git a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 9fdae4bd..886a605f 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -3425,6 +3425,7 @@ test_roundtrip_ethtool(void) gs_unref_object NMConnection *connection = NULL; NMSetting *s_ethtool; NMSetting *s_wired; + int i_run; connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", NULL, @@ -3487,6 +3488,159 @@ test_roundtrip_ethtool(void) TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-5.cexpected", NULL); g_clear_object(&connection); + + connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); + g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, TRUE, NULL); + + s_ethtool = _nm_connection_new_setting(connection, NM_TYPE_SETTING_ETHTOOL); + nm_setting_option_set_boolean(s_ethtool, NM_ETHTOOL_OPTNAME_PAUSE_AUTONEG, FALSE); + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-6.cexpected", + NULL); + g_clear_object(&connection); + + connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); + g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, TRUE, NULL); + + s_ethtool = _nm_connection_new_setting(connection, NM_TYPE_SETTING_ETHTOOL); + nm_setting_option_set_uint32(s_ethtool, NM_ETHTOOL_OPTNAME_RING_RX, 512); + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-7.cexpected", + NULL); + g_clear_object(&connection); + + connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); + g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, TRUE, NULL); + + s_ethtool = _nm_connection_new_setting(connection, NM_TYPE_SETTING_ETHTOOL); + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-8.cexpected", + NULL); + g_clear_object(&connection); + + connection = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_wired = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_WIRED); + g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, TRUE, NULL); + + s_ethtool = _nm_connection_new_setting(connection, NM_TYPE_SETTING_ETHTOOL); + nm_setting_option_set_boolean(s_ethtool, NM_ETHTOOL_OPTNAME_PAUSE_AUTONEG, FALSE); + nm_setting_option_set_uint32(s_ethtool, NM_ETHTOOL_OPTNAME_RING_RX, 512); + _writer_new_connec_exp(connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test_roundtrip_ethtool-9.cexpected", + NULL); + g_clear_object(&connection); + + for (i_run = 0; i_run < 20; i_run++) { + gs_unref_object NMConnection *con2 = NULL; + gs_unref_object NMConnection *reread = NULL; + nmtst_auto_unlinkfile char *testfile = NULL; + gboolean reread_same; + gboolean v_bool; + NMEthtoolID ethtool_ids[_NM_ETHTOOL_ID_NUM]; + guint i; + guint l; + NMSettingWiredWakeOnLan wake_on_lan; + + con2 = nmtst_create_minimal_connection("test_roundtrip_ethtool", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_wired = nmtst_connection_assert_setting(con2, NM_TYPE_SETTING_WIRED); + g_object_set(s_wired, NM_SETTING_WIRED_AUTO_NEGOTIATE, nmtst_get_rand_bool(), NULL); + + if (nmtst_get_rand_bool()) { + g_object_set(s_wired, + NM_SETTING_WIRED_SPEED, + 1000u, + NM_SETTING_WIRED_DUPLEX, + nmtst_get_rand_bool() ? "full" : "half", + NULL); + } + + wake_on_lan = nmtst_get_rand_uint32(); + wake_on_lan = wake_on_lan & NM_SETTING_WIRED_WAKE_ON_LAN_ALL; + wake_on_lan = nmtst_rand_select(wake_on_lan, + NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT, + NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE); + g_object_set(s_wired, NM_SETTING_WIRED_WAKE_ON_LAN, (guint) wake_on_lan, NULL); + + if (NM_FLAGS_HAS(wake_on_lan, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC) + && nmtst_get_rand_bool()) { + g_object_set(s_wired, NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, "aa:bb:cc:dd:ee:ff", NULL); + } + + l = nmtst_get_rand_uint32() % (G_N_ELEMENTS(ethtool_ids) + 2); + if (l == 0) { + /* pass. No ethtool setting. */ + goto check_roundtrip; + } + l--; + + s_ethtool = _nm_connection_new_setting(con2, NM_TYPE_SETTING_ETHTOOL); + + for (i = 0; i < (int) G_N_ELEMENTS(ethtool_ids); i++) + ethtool_ids[i] = i; + nmtst_rand_perm(NULL, ethtool_ids, NULL, sizeof(ethtool_ids[0]), G_N_ELEMENTS(ethtool_ids)); + + for (i = 0; i < l; i++) { + NMEthtoolID ethtool_id = ethtool_ids[i]; + const GVariantType *vtype; + const char *optname; + + optname = nm_ethtool_data[ethtool_id]->optname; + vtype = nm_ethtool_id_get_variant_type(ethtool_id); + + if (NM_IN_SET(ethtool_id, + NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX, + NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)) { + nm_setting_option_set_uint32(s_ethtool, optname, nmtst_get_rand_uint32() % 2); + } else if (g_variant_type_equal(vtype, G_VARIANT_TYPE_BOOLEAN)) + nm_setting_option_set_boolean(s_ethtool, optname, nmtst_get_rand_bool()); + else if (g_variant_type_equal(vtype, G_VARIANT_TYPE_UINT32)) + nm_setting_option_set_uint32(s_ethtool, optname, nmtst_get_rand_uint32()); + else + g_assert_not_reached(); + } + + if ((nm_setting_option_get_boolean(s_ethtool, NM_ETHTOOL_OPTNAME_PAUSE_RX, NULL) + || nm_setting_option_get_boolean(s_ethtool, NM_ETHTOOL_OPTNAME_PAUSE_TX, NULL)) + && nm_setting_option_get_boolean(s_ethtool, NM_ETHTOOL_OPTNAME_PAUSE_AUTONEG, &v_bool) + && v_bool) { + /* don't accidentally create an invalid profile. */ + nm_setting_option_set(s_ethtool, + NM_ETHTOOL_OPTNAME_PAUSE_AUTONEG, + nmtst_get_rand_bool() ? g_variant_new_boolean(FALSE) : NULL); + } + +check_roundtrip: + _writer_new_connection_reread(con2, + TEST_SCRATCH_DIR, + &testfile, + NO_EXPECTED, + &reread, + &reread_same); + g_assert(NM_IS_CONNECTION(reread)); + g_assert(reread_same); + } } static void @@ -8211,8 +8365,35 @@ test_read_infiniband(void) } static void -test_write_infiniband(void) +test_read_ipoib(void) +{ + gs_unref_object NMConnection *connection = NULL; + NMSettingInfiniband *s_infiniband; + char *unmanaged = NULL; + const char *transport_mode; + int pkey; + + connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-ipoib", + NULL, + TYPE_INFINIBAND, + &unmanaged); + g_assert(!unmanaged); + + s_infiniband = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_INFINIBAND); + + pkey = nm_setting_infiniband_get_p_key(s_infiniband); + g_assert(pkey); + g_assert_cmpint(pkey, ==, 12); + + transport_mode = nm_setting_infiniband_get_transport_mode(s_infiniband); + g_assert(transport_mode); + g_assert_cmpstr(transport_mode, ==, "connected"); +} + +static void +test_write_infiniband(gconstpointer test_data) { + const int TEST_IDX = GPOINTER_TO_INT(test_data); nmtst_auto_unlinkfile char *testfile = NULL; gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; @@ -8223,14 +8404,15 @@ test_write_infiniband(void) const char *mac = "80:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22"; guint32 mtu = 65520; NMIPAddress *addr; - GError *error = NULL; + GError *error = NULL; + const char *interface_name = NULL; connection = nm_simple_connection_new(); s_con = _nm_connection_new_setting(connection, NM_TYPE_SETTING_CONNECTION); g_object_set(s_con, NM_SETTING_CONNECTION_ID, - "Test Write InfiniBand", + "Test Write Infiniband", NM_SETTING_CONNECTION_UUID, nm_uuid_generate_random_str_a(), NM_SETTING_CONNECTION_AUTOCONNECT, @@ -8239,15 +8421,28 @@ test_write_infiniband(void) NM_SETTING_INFINIBAND_SETTING_NAME, NULL); + if (NM_IN_SET(TEST_IDX, 1, 3)) + interface_name = "ib0.000c"; + + g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name, NULL); + s_infiniband = _nm_connection_new_setting(connection, NM_TYPE_SETTING_INFINIBAND); - g_object_set(s_infiniband, - NM_SETTING_INFINIBAND_MAC_ADDRESS, - mac, - NM_SETTING_INFINIBAND_MTU, - mtu, - NM_SETTING_INFINIBAND_TRANSPORT_MODE, - "connected", - NULL); + g_object_set(s_infiniband, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected", NULL); + if (NM_IN_SET(TEST_IDX, 1, 2)) { + g_object_set(s_infiniband, + NM_SETTING_INFINIBAND_MAC_ADDRESS, + mac, + NM_SETTING_INFINIBAND_MTU, + mtu, + NULL); + } else { + g_object_set(s_infiniband, + NM_SETTING_INFINIBAND_P_KEY, + 12, + NM_SETTING_INFINIBAND_PARENT, + "ib0", + NULL); + } s_ip4 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP4_CONFIG); g_object_set(s_ip4, @@ -8267,6 +8462,9 @@ test_write_infiniband(void) s_ip6 = _nm_connection_new_setting(connection, NM_TYPE_SETTING_IP6_CONFIG); g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); + if (nmtst_get_rand_bool()) + nmtst_connection_normalize(connection); + nmtst_assert_connection_verifies(connection); _writer_new_connection(connection, TEST_SCRATCH_DIR, &testfile); @@ -8274,6 +8472,8 @@ test_write_infiniband(void) reread = _connection_from_file(testfile, NULL, TYPE_INFINIBAND, NULL); nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); + + g_assert_cmpstr(interface_name, ==, nm_connection_get_interface_name(reread)); } static void @@ -10446,6 +10646,7 @@ main(int argc, char **argv) g_test_add_func(TPATH "wifi/read/wep-no-keys", test_read_wifi_wep_no_keys); g_test_add_func(TPATH "wifi/read/wep-agent-keys", test_read_wifi_wep_agent_keys); g_test_add_func(TPATH "infiniband/read", test_read_infiniband); + g_test_add_func(TPATH "ipoib/read", test_read_ipoib); g_test_add_func(TPATH "vlan/read", test_read_vlan_interface); g_test_add_func(TPATH "vlan/read-flags-1", test_read_vlan_flags_1); g_test_add_func(TPATH "vlan/read-flags-2", test_read_vlan_flags_2); @@ -10582,7 +10783,10 @@ main(int argc, char **argv) g_test_add_func(TPATH "permissions/read", test_read_permissions); g_test_add_func(TPATH "permissions/write", test_write_permissions); g_test_add_func(TPATH "wifi/write-wep-agent-keys", test_write_wifi_wep_agent_keys); - g_test_add_func(TPATH "infiniband/write", test_write_infiniband); + g_test_add_data_func(TPATH "infiniband/write/1", GINT_TO_POINTER(1), test_write_infiniband); + g_test_add_data_func(TPATH "infiniband/write/2", GINT_TO_POINTER(2), test_write_infiniband); + g_test_add_data_func(TPATH "infiniband/write/3", GINT_TO_POINTER(3), test_write_infiniband); + g_test_add_data_func(TPATH "infiniband/write/4", GINT_TO_POINTER(4), test_write_infiniband); g_test_add_func(TPATH "vlan/write", test_write_vlan); g_test_add_func(TPATH "vlan/write-flags", test_write_vlan_flags); g_test_add_func(TPATH "vlan/write-only-vlanid", test_write_vlan_only_vlanid); diff --git a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c index 1307d4b2..47be3a5e 100644 --- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -2292,14 +2292,19 @@ test_read_missing_vlan_flags(void) static void test_read_missing_id_uuid(void) { - gs_unref_object NMConnection *connection = NULL; - gs_free char *expected_uuid = NULL; - const char *FILENAME = TEST_KEYFILES_DIR "/Test_Missing_ID_UUID"; + gs_unref_object NMConnection *connection = NULL; + gs_free char *expected_uuid = NULL; + gs_free char *expected_uuid2 = NULL; + const char *FILENAME = TEST_KEYFILES_DIR "/Test_Missing_ID_UUID"; + const char F[] = "keyfile\0" TEST_KEYFILES_DIR "/Test_Missing_ID_UUID"; expected_uuid = nm_uuid_generate_from_strings("keyfile", FILENAME, NULL); - connection = keyfile_read_connection_from_file(FILENAME); + expected_uuid2 = + nm_uuid_generate_from_string_str(F, sizeof(F), NM_UUID_TYPE_VERSION3, &nm_uuid_ns_1); + g_assert_cmpstr(expected_uuid, ==, expected_uuid2); + connection = keyfile_read_connection_from_file(FILENAME); g_assert_cmpstr(nm_connection_get_id(connection), ==, "Test_Missing_ID_UUID"); g_assert_cmpstr(nm_connection_get_uuid(connection), ==, expected_uuid); } diff --git a/src/libnm-base/nm-ethtool-base.c b/src/libnm-base/nm-ethtool-base.c index 99bbe68e..78e9fbc1 100644 --- a/src/libnm-base/nm-ethtool-base.c +++ b/src/libnm-base/nm-ethtool-base.c @@ -294,3 +294,15 @@ nm_ethtool_id_to_type(NMEthtoolID id) return NM_ETHTOOL_TYPE_UNKNOWN; } + +const GVariantType * +nm_ethtool_id_get_variant_type(NMEthtoolID ethtool_id) +{ + if (nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id)) + return G_VARIANT_TYPE_BOOLEAN; + + if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id)) + return G_VARIANT_TYPE_UINT32; + + return NULL; +} diff --git a/src/libnm-base/nm-ethtool-base.h b/src/libnm-base/nm-ethtool-base.h index abedcafe..22bb88fb 100644 --- a/src/libnm-base/nm-ethtool-base.h +++ b/src/libnm-base/nm-ethtool-base.h @@ -21,6 +21,8 @@ const NMEthtoolData *nm_ethtool_data_get_by_optname(const char *optname); NMEthtoolType nm_ethtool_id_to_type(NMEthtoolID id); +const GVariantType *nm_ethtool_id_get_variant_type(NMEthtoolID ethtool_id); + /****************************************************************************/ static inline NMEthtoolID diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver index e414b7e6..2478defa 100644 --- a/src/libnm-client-impl/libnm.ver +++ b/src/libnm-client-impl/libnm.ver @@ -1844,3 +1844,37 @@ global: nm_setting_ip4_link_local_get_type; nm_setting_ip6_config_get_mtu; } libnm_1_38_0; + +libnm_1_40_4 { +global: + nm_device_6lowpan_get_parent; + nm_device_macsec_get_parent; + nm_device_veth_get_peer; + nm_device_vxlan_get_carrier; + nm_device_vxlan_get_rsc; + nm_device_wifi_p2p_get_peer_by_path; + nm_setting_6lowpan_get_parent; + nm_setting_6lowpan_new; + nm_setting_connection_get_mptcp_flags; + nm_setting_hostname_new; + nm_setting_ip4_config_get_link_local; + nm_setting_ip_config_get_dhcp_iaid; + nm_setting_ip_tunnel_get_encapsulation_limit; + nm_setting_ip_tunnel_get_flow_label; + nm_setting_ovs_bridge_get_datapath_type; + nm_setting_vpn_get_persistent; + nm_setting_wpan_get_channel; + nm_setting_wpan_get_mac_address; + nm_setting_wpan_get_page; + nm_setting_wpan_get_pan_id; + nm_setting_wpan_get_short_address; + nm_setting_wpan_new; + nm_sriov_vf_attribute_validate; + nm_tc_tfilter_get_action; + nm_tc_tfilter_set_action; + nm_utils_ip_addresses_from_variant; + nm_utils_ip_addresses_to_variant; + nm_utils_ip_routes_from_variant; + nm_utils_ip_routes_to_variant; + nm_vpn_plugin_info_supports_multiple; +} libnm_1_40_0; diff --git a/src/libnm-client-impl/meson.build b/src/libnm-client-impl/meson.build index 46464a63..d72ed545 100644 --- a/src/libnm-client-impl/meson.build +++ b/src/libnm-client-impl/meson.build @@ -236,5 +236,4 @@ if enable_introspection ], depends: libnm_gir, ) - endif diff --git a/src/libnm-client-impl/nm-client.c b/src/libnm-client-impl/nm-client.c index a2ca8333..871c5466 100644 --- a/src/libnm-client-impl/nm-client.c +++ b/src/libnm-client-impl/nm-client.c @@ -5248,7 +5248,7 @@ _add_and_activate_connection(NMClient *self, * @partial: (allow-none): an #NMConnection to add; the connection may be * partially filled (or even %NULL) and will be completed by NetworkManager * using the given @device and @specific_object before being added - * @device: the #NMDevice + * @device: (allow-none): the #NMDevice * @specific_object: (allow-none): the object path of a connection-type-specific * object this activation should use. This parameter is currently ignored for * wired and mobile broadband connections, and the value of %NULL should be used @@ -5322,7 +5322,7 @@ nm_client_add_and_activate_connection_finish(NMClient *client, GAsyncResult *res * @partial: (allow-none): an #NMConnection to add; the connection may be * partially filled (or even %NULL) and will be completed by NetworkManager * using the given @device and @specific_object before being added - * @device: the #NMDevice + * @device: (allow-none): the #NMDevice * @specific_object: (allow-none): the object path of a connection-type-specific * object this activation should use. This parameter is currently ignored for * wired and mobile broadband connections, and the value of %NULL should be used @@ -5396,6 +5396,8 @@ nm_client_add_and_activate_connection2(NMClient *client, * * Returns: (transfer full): the new #NMActiveConnection on success, %NULL on * failure, in which case @error will be set. + * + * Since: 1.16 **/ NMActiveConnection * nm_client_add_and_activate_connection2_finish(NMClient *client, diff --git a/src/libnm-client-impl/nm-device-6lowpan.c b/src/libnm-client-impl/nm-device-6lowpan.c index 39558f25..fc1f59ba 100644 --- a/src/libnm-client-impl/nm-device-6lowpan.c +++ b/src/libnm-client-impl/nm-device-6lowpan.c @@ -39,7 +39,7 @@ G_DEFINE_TYPE(NMDevice6Lowpan, nm_device_6lowpan, NM_TYPE_DEVICE) * * Returns: (transfer none): the device's parent device * - * Since: 1.14 + * Since: 1.42, 1.40.4 **/ NMDevice * nm_device_6lowpan_get_parent(NMDevice6Lowpan *device) @@ -49,27 +49,6 @@ nm_device_6lowpan_get_parent(NMDevice6Lowpan *device) return nml_dbus_property_o_get_obj(&NM_DEVICE_6LOWPAN_GET_PRIVATE(device)->parent); } -/** - * nm_device_6lowpan_get_hw_address: (skip) - * @device: a #NMDevice6Lowpan - * - * Gets the hardware (MAC) address of the #NMDevice6Lowpan - * - * Returns: the hardware address. This is the internal string used by the - * device, and must not be modified. - * - * Since: 1.14 - * - * Deprecated: 1.24: Use nm_device_get_hw_address() instead. - **/ -const char * -nm_device_6lowpan_get_hw_address(NMDevice6Lowpan *device) -{ - g_return_val_if_fail(NM_IS_DEVICE_6LOWPAN(device), NULL); - - return nm_device_get_hw_address(NM_DEVICE(device)); -} - /*****************************************************************************/ static void diff --git a/src/libnm-client-impl/nm-device-macsec.c b/src/libnm-client-impl/nm-device-macsec.c index 525d32d0..763faa6c 100644 --- a/src/libnm-client-impl/nm-device-macsec.c +++ b/src/libnm-client-impl/nm-device-macsec.c @@ -65,7 +65,7 @@ G_DEFINE_TYPE(NMDeviceMacsec, nm_device_macsec, NM_TYPE_DEVICE) * * Returns: (transfer none): the device's parent device * - * Since: 1.6 + * Since: 1.42, 1.40.4 **/ NMDevice * nm_device_macsec_get_parent(NMDeviceMacsec *device) diff --git a/src/libnm-client-impl/nm-device-tun.c b/src/libnm-client-impl/nm-device-tun.c index 353b4bdc..2e75c860 100644 --- a/src/libnm-client-impl/nm-device-tun.c +++ b/src/libnm-client-impl/nm-device-tun.c @@ -124,7 +124,7 @@ nm_device_tun_get_group(NMDeviceTun *device) } /** - * nm_device_tun_get_pi: + * nm_device_tun_get_no_pi: * @device: a #NMDeviceTun * * Returns whether the #NMDeviceTun has the IFF_NO_PI flag. diff --git a/src/libnm-client-impl/nm-device-veth.c b/src/libnm-client-impl/nm-device-veth.c index d9fc325b..0d4537ed 100644 --- a/src/libnm-client-impl/nm-device-veth.c +++ b/src/libnm-client-impl/nm-device-veth.c @@ -44,7 +44,7 @@ G_DEFINE_TYPE(NMDeviceVeth, nm_device_veth, NM_TYPE_DEVICE_ETHERNET) * * Returns: (transfer none): the device's peer device * - * Since: 1.30 + * Since: 1.42, 1.40.4 **/ NMDevice * nm_device_veth_get_peer(NMDeviceVeth *device) diff --git a/src/libnm-client-impl/nm-device-vxlan.c b/src/libnm-client-impl/nm-device-vxlan.c index d81b5516..13c20536 100644 --- a/src/libnm-client-impl/nm-device-vxlan.c +++ b/src/libnm-client-impl/nm-device-vxlan.c @@ -99,7 +99,7 @@ nm_device_vxlan_get_hw_address(NMDeviceVxlan *device) * This property is not implemented yet, and the function always returns * FALSE. * - * Since: 1.2 + * Since: 1.42, 1.40.4 **/ gboolean nm_device_vxlan_get_carrier(NMDeviceVxlan *device) @@ -325,7 +325,7 @@ nm_device_vxlan_get_proxy(NMDeviceVxlan *device) * * Returns: whether route short circuit is turned on * - * Since: 1.2 + * Since: 1.42, 1.40.4 **/ gboolean nm_device_vxlan_get_rsc(NMDeviceVxlan *device) diff --git a/src/libnm-client-impl/nm-device-wifi-p2p.c b/src/libnm-client-impl/nm-device-wifi-p2p.c index 6e667ac6..3d539111 100644 --- a/src/libnm-client-impl/nm-device-wifi-p2p.c +++ b/src/libnm-client-impl/nm-device-wifi-p2p.c @@ -100,7 +100,7 @@ nm_device_wifi_p2p_get_peers(NMDeviceWifiP2P *device) * * Returns: (transfer none): the peer or %NULL if none is found. * - * Since: 1.16 + * Since: 1.42, 1.40.4 **/ NMWifiP2PPeer * nm_device_wifi_p2p_get_peer_by_path(NMDeviceWifiP2P *device, const char *path) diff --git a/src/libnm-client-impl/nm-device-wpan.c b/src/libnm-client-impl/nm-device-wpan.c index 30c1ea16..337e3de0 100644 --- a/src/libnm-client-impl/nm-device-wpan.c +++ b/src/libnm-client-impl/nm-device-wpan.c @@ -24,25 +24,6 @@ struct _NMDeviceWpanClass { G_DEFINE_TYPE(NMDeviceWpan, nm_device_wpan, NM_TYPE_DEVICE) /*****************************************************************************/ -/** - * nm_device_wpan_get_hw_address: (skip) - * @device: a #NMDeviceWpan - * - * Gets the active hardware (MAC) address of the #NMDeviceWpan - * - * Returns: the active hardware address. This is the internal string used by the - * device, and must not be modified. - * - * Deprecated: 1.24: Use nm_device_get_hw_address() instead. - **/ -const char * -nm_device_wpan_get_hw_address(NMDeviceWpan *device) -{ - g_return_val_if_fail(NM_IS_DEVICE_WPAN(device), NULL); - - return nm_device_get_hw_address(NM_DEVICE(device)); -} - static gboolean connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { diff --git a/src/libnm-client-impl/nm-remote-connection.c b/src/libnm-client-impl/nm-remote-connection.c index 23dfc1da..b10d3d55 100644 --- a/src/libnm-client-impl/nm-remote-connection.c +++ b/src/libnm-client-impl/nm-remote-connection.c @@ -125,6 +125,8 @@ nm_remote_connection_update2(NMRemoteConnection *connection, * * Returns: (transfer full): on success, a #GVariant of type "a{sv}" with the result. On failure, * %NULL. + * + * Since: 1.12 **/ GVariant * nm_remote_connection_update2_finish(NMRemoteConnection *connection, diff --git a/src/libnm-client-impl/nm-settings-docs-gir.xml b/src/libnm-client-impl/nm-settings-docs-gir.xml index 3ce853e4..eef7de67 100644 --- a/src/libnm-client-impl/nm-settings-docs-gir.xml +++ b/src/libnm-client-impl/nm-settings-docs-gir.xml @@ -145,9 +145,7 @@ This property is currently not implemented for DHCPv6.</description><description-docbook><para> Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers.</para><para> For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. "192.168.122.0/24").</para><para> This property is currently not implemented for DHCPv6.</para></description-docbook></property><property name="dhcp-send-hostname" name_upper="DHCP_SEND_HOSTNAME" type="boolean" default="TRUE"><description> If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the "dhcp-hostname" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.</description><description-docbook><para> If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the "dhcp-hostname" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.</para></description-docbook></property><property name="dhcp-timeout" name_upper="DHCP_TIMEOUT" type="int32" default="0"><description> A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). - Set to 2147483647 (MAXINT32) for infinity.</description><description-docbook><para> A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds).</para><para> Set to 2147483647 (MAXINT32) for infinity.</para></description-docbook></property><property name="dhcp-vendor-class-identifier" name_upper="DHCP_VENDOR_CLASS_IDENTIFIER" type="string"><description> The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server. - - Since 1.28</description><description-docbook><para> The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server.</para><para> Since 1.28</para></description-docbook></property><property name="dns" name_upper="DNS" type="array of uint32"><description> Array of IP addresses of DNS servers.</description><description-docbook><para> Array of IP addresses of DNS servers.</para></description-docbook></property><property name="dns-options" name_upper="DNS_OPTIONS" type="array of string"><description> Array of DNS options as described in man 5 resolv.conf. + Set to 2147483647 (MAXINT32) for infinity.</description><description-docbook><para> A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds).</para><para> Set to 2147483647 (MAXINT32) for infinity.</para></description-docbook></property><property name="dhcp-vendor-class-identifier" name_upper="DHCP_VENDOR_CLASS_IDENTIFIER" type="string"><description> The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server.</description><description-docbook><para> The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server.</para></description-docbook></property><property name="dns" name_upper="DNS" type="array of uint32"><description> Array of IP addresses of DNS servers.</description><description-docbook><para> Array of IP addresses of DNS servers.</para></description-docbook></property><property name="dns-options" name_upper="DNS_OPTIONS" type="array of string"><description> Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties. @@ -179,9 +177,7 @@ Note that the gateway usually conflicts with routing that NetworkManager configures for WireGuard interfaces, so usually it should not be set in that case. See "ip4-auto-default-route".</description><description-docbook><para> The gateway associated with this configuration. This is only meaningful if "addresses" is also set.</para><para> Setting the gateway causes NetworkManager to configure a standard default route with the gateway as next hop. This is ignored if "never-default" is set. An alternative is to configure the default route explicitly with a manual route and /0 as prefix length.</para><para> Note that the gateway usually conflicts with routing that NetworkManager configures for WireGuard interfaces, so usually it should not be set in that case. See "ip4-auto-default-route".</para></description-docbook></property><property name="ignore-auto-dns" name_upper="IGNORE_AUTO_DNS" type="boolean" default="FALSE"><description> When "method" is set to "auto" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the "dns" and "dns-search" properties, if any, are used.</description><description-docbook><para> When "method" is set to "auto" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the "dns" and "dns-search" properties, if any, are used.</para></description-docbook></property><property name="ignore-auto-routes" name_upper="IGNORE_AUTO_ROUTES" type="boolean" default="FALSE"><description> When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used.</description><description-docbook><para> When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used.</para></description-docbook></property><property name="link-local" name_upper="LINK_LOCAL" type="int32" default="0"><description> Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. - When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default". - - Since 1.40</description><description-docbook><para> Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server.</para><para> When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default".</para><para> Since 1.40</para></description-docbook></property><property name="may-fail" name_upper="MAY_FAIL" type="boolean" default="TRUE"><description> If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.</description><description-docbook><para> If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.</para></description-docbook></property><property name="method" name_upper="METHOD" type="string"><description> IP configuration method. + When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default".</description><description-docbook><para> Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server.</para><para> When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default".</para></description-docbook></property><property name="may-fail" name_upper="MAY_FAIL" type="boolean" default="TRUE"><description> If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.</description><description-docbook><para> If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.</para></description-docbook></property><property name="method" name_upper="METHOD" type="string"><description> IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support "disabled", "auto", "manual", and "link-local". See the subclass-specific documentation for other values. diff --git a/src/libnm-client-impl/nm-vpn-plugin-old.c b/src/libnm-client-impl/nm-vpn-plugin-old.c index 19ba2bb0..8898f09a 100644 --- a/src/libnm-client-impl/nm-vpn-plugin-old.c +++ b/src/libnm-client-impl/nm-vpn-plugin-old.c @@ -281,13 +281,8 @@ schedule_fail_stop(NMVpnPluginOld *plugin, guint timeout_secs) priv->fail_stop_id = g_idle_add(fail_stop, plugin); } -/** - * nm_vpn_plugin_old_set_config: - * - * Deprecated: 1.2: Replaced by NMVpnServicePlugin. - */ -void -nm_vpn_plugin_old_set_config(NMVpnPluginOld *plugin, GVariant *config) +static void +set_config(NMVpnPluginOld *plugin, GVariant *config) { NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE(plugin); @@ -382,13 +377,8 @@ nm_vpn_plugin_old_set_ip4_config(NMVpnPluginOld *plugin, GVariant *ip4_config) nm_vpn_plugin_old_set_state(plugin, NM_VPN_SERVICE_STATE_STARTED); } -/** - * nm_vpn_plugin_old_set_ip6_config: - * - * Deprecated: 1.2: Replaced by NMVpnServicePlugin. - */ -void -nm_vpn_plugin_old_set_ip6_config(NMVpnPluginOld *plugin, GVariant *ip6_config) +static void +set_ip6_config(NMVpnPluginOld *plugin, GVariant *ip6_config) { NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE(plugin); @@ -721,7 +711,7 @@ impl_vpn_plugin_old_set_config(NMVpnPluginOld *plugin, GVariant *config, gpointer user_data) { - nm_vpn_plugin_old_set_config(plugin, config); + set_config(plugin, config); g_dbus_method_invocation_return_value(context, NULL); } @@ -741,7 +731,7 @@ impl_vpn_plugin_old_set_ip6_config(NMVpnPluginOld *plugin, GVariant *config, gpointer user_data) { - nm_vpn_plugin_old_set_ip6_config(plugin, config); + set_ip6_config(plugin, config); g_dbus_method_invocation_return_value(context, NULL); } diff --git a/src/libnm-client-impl/nm-vpn-service-plugin.c b/src/libnm-client-impl/nm-vpn-service-plugin.c index 3493d1db..d26a4ff5 100644 --- a/src/libnm-client-impl/nm-vpn-service-plugin.c +++ b/src/libnm-client-impl/nm-vpn-service-plugin.c @@ -136,6 +136,11 @@ nm_vpn_service_plugin_set_state(NMVpnServicePlugin *plugin, NMVpnServiceState st } } +/** + * nm_vpn_service_plugin_set_login_banner: + * + * Since: 1.2 + */ void nm_vpn_service_plugin_set_login_banner(NMVpnServicePlugin *plugin, const char *banner) { @@ -160,6 +165,11 @@ _emit_failure(NMVpnServicePlugin *plugin, NMVpnPluginFailure reason) nmdbus_vpn_plugin_emit_failure(priv->dbus_vpn_service_plugin, reason); } +/** + * nm_vpn_service_plugin_failure: + * + * Since: 1.2 + */ void nm_vpn_service_plugin_failure(NMVpnServicePlugin *plugin, NMVpnPluginFailure reason) { @@ -169,6 +179,11 @@ nm_vpn_service_plugin_failure(NMVpnServicePlugin *plugin, NMVpnPluginFailure rea nm_vpn_service_plugin_disconnect(plugin, NULL); } +/** + * nm_vpn_service_plugin_disconnect: + * + * Since: 1.2 + */ gboolean nm_vpn_service_plugin_disconnect(NMVpnServicePlugin *plugin, GError **err) { @@ -326,6 +341,11 @@ schedule_fail_stop(NMVpnServicePlugin *plugin, guint timeout_secs) priv->fail_stop_id = g_idle_add(fail_stop, plugin); } +/** + * nm_vpn_service_plugin_set_config: + * + * Since: 1.2 + */ void nm_vpn_service_plugin_set_config(NMVpnServicePlugin *plugin, GVariant *config) { @@ -364,6 +384,11 @@ nm_vpn_service_plugin_set_config(NMVpnServicePlugin *plugin, GVariant *config) nm_vpn_service_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STARTED); } +/** + * nm_vpn_service_plugin_set_ip4_config: + * + * Since: 1.2 + */ void nm_vpn_service_plugin_set_ip4_config(NMVpnServicePlugin *plugin, GVariant *ip4_config) { @@ -422,6 +447,11 @@ nm_vpn_service_plugin_set_ip4_config(NMVpnServicePlugin *plugin, GVariant *ip4_c nm_vpn_service_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STARTED); } +/** + * nm_vpn_service_plugin_set_ip6_config: + * + * Since: 1.2 + */ void nm_vpn_service_plugin_set_ip6_config(NMVpnServicePlugin *plugin, GVariant *ip6_config) { diff --git a/src/libnm-client-impl/tests/meson.build b/src/libnm-client-impl/tests/meson.build index 3f2e78a7..0c0e188b 100644 --- a/src/libnm-client-impl/tests/meson.build +++ b/src/libnm-client-impl/tests/meson.build @@ -44,3 +44,15 @@ foreach test_unit: test_units args: test_args + [exe.full_path()], ) endforeach + +if enable_introspection + test( + 'check-local-libnm-gir', + python, + args: [ + join_paths(meson.source_root(), 'src', 'libnm-client-impl', 'tests', 'test-gir.py'), + '--gir', libnm_gir[0], + '--ver', join_paths(meson.source_root(), 'src', 'libnm-client-impl', 'libnm.ver'), + ], + ) +endif diff --git a/src/libnm-client-impl/tests/test-gir.py b/src/libnm-client-impl/tests/test-gir.py new file mode 100755 index 00000000..d91849b8 --- /dev/null +++ b/src/libnm-client-impl/tests/test-gir.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2022 Red Hat, Inc. +# + +from __future__ import print_function +import xml.etree.ElementTree as ET +import argparse +import sys + +C_NS = "http://www.gtk.org/introspection/c/1.0" +CORE_NS = "http://www.gtk.org/introspection/core/1.0" +GLIB_NS = "http://www.gtk.org/introspection/glib/1.0" + + +def syms_from_gir(girfile): + def xml_symbols(xml, types): + ret = [] + for t in types: + ret += xml.findall("./{%s}namespace/{%s}%s" % (CORE_NS, CORE_NS, t)) + ret += xml.findall("./{%s}namespace/*/{%s}%s" % (CORE_NS, CORE_NS, t)) + return ret + + girxml = ET.parse(girfile) + c_syms = {} + for sym in xml_symbols(girxml, ("constructor", "function", "method")): + c_syms[sym.get("{%s}identifier" % C_NS)] = sym.get("version") + + for sym in xml_symbols( + girxml, ("bitfield", "class", "enumeration", "interface", "record") + ): + get_type = sym.get("{%s}get-type" % GLIB_NS) + if get_type is None: + continue + version = sym.get("version") + + if version is None: + # FIXME: The get_type() functions should be exported in the same + # version the type itself appeared. However, a large number of + # classes lack Since: tags in their doc blocks. Fall back to using + # the tag on _new() method for the test to be able to proceed + # reasonably. This should be fixed eventually. + constructor = sym.find("./{%s}constructor" % CORE_NS) + if constructor is not None: + version = constructor.get("version") + + c_syms[get_type] = version + return c_syms + + +# Older Python doesn't have str.removesuffix() +def str_removesuffix(string, suffix): + try: + return string.removesuffix(suffix) + except AttributeError: + if string.endswith(suffix): + return string[: -len(suffix)] + else: + return string + + +# Older Python doesn't have str.removeprefix() +def str_removeprefix(string, prefix): + try: + return string.removeprefix(prefix) + except AttributeError: + if string.startswith(prefix): + return string[len(prefix) :] + else: + return string + + +def syms_from_ver(verfile): + c_syms = {} + for line in open(verfile).readlines(): + line = line.strip() + + if line.endswith("{"): + line = str_removesuffix(line, " {") + line = str_removeprefix(line, "libnm_") + (major, minor, micro) = line.split("_") + if int(major) > 1 or int(minor) > 0: + if int(micro) > 0: + # Snap to next major version. Perhaps not + # exactly correct, but good for all symbols + # we export but nm_ethtool_optname_is_feature(). + minor = str(int(minor) + 2) + version = major + "." + minor + else: + version = None + elif ( + line.endswith(";") + and not line.startswith("}") + and not line.startswith("#") + and not line == "*;" + ): + c_syms[str_removesuffix(line, ";")] = version + + # This one is... messy. + c_syms["nm_ethtool_optname_is_feature"] = "1.20" + + return c_syms + + +parser = argparse.ArgumentParser() +parser.add_argument( + "--gir", + metavar="FILE", + help="NM-1.0.gir file", + required=True, +) +parser.add_argument( + "--ver", + metavar="FILE", + help="libnm.ver file", + required=True, +) + +args = parser.parse_args() + +gir_syms = syms_from_gir(args.gir) +ver_syms = syms_from_ver(args.ver) + +exit_code = 0 + +for (gir_sym, gir_ver) in gir_syms.items(): + if gir_sym not in ver_syms: + exit_code = 1 + print( + 'FAIL: "%s" found in "%s", but is not exported. Needs adding to "%s"?' + % (gir_sym, args.gir, args.ver), + file=sys.stderr, + ) + continue + if gir_ver != ver_syms[gir_sym]: + exit_code = 1 + print( + 'FAIL: "%s" exported in version "%s" but documented as available since "%s"' + % (gir_sym, ver_syms[gir_sym], gir_ver), + file=sys.stderr, + ) + +# In python2, dict.keys() returns lists, not sets. Cast them. +for sym in set(ver_syms.keys()) - set(gir_syms.keys()): + exit_code = 1 + print( + 'FAIL: "%s" found in "%s", but not in "%s". Maybe the doc comment is wrong or g-ir-scanner messed up?' + % (sym, args.ver, args.gir), + file=sys.stderr, + ) + +sys.exit(exit_code) diff --git a/src/libnm-client-public/nm-checkpoint.h b/src/libnm-client-public/nm-checkpoint.h index 456d7f6b..c47ff39c 100644 --- a/src/libnm-client-public/nm-checkpoint.h +++ b/src/libnm-client-public/nm-checkpoint.h @@ -29,6 +29,8 @@ G_BEGIN_DECLS /** * NMCheckpoint: + * + * Since: 1.12 */ typedef struct _NMCheckpoint NMCheckpoint; typedef struct _NMCheckpointClass NMCheckpointClass; diff --git a/src/libnm-client-public/nm-client.h b/src/libnm-client-public/nm-client.h index 6307f112..da5e509e 100644 --- a/src/libnm-client-public/nm-client.h +++ b/src/libnm-client-public/nm-client.h @@ -120,6 +120,11 @@ GQuark nm_client_error_quark(void); /* DNS stuff */ +/** + * NMDnsEntry: + * + * Since: 1.6 + */ typedef struct NMDnsEntry NMDnsEntry; NM_AVAILABLE_IN_1_6 diff --git a/src/libnm-client-public/nm-device-6lowpan.h b/src/libnm-client-public/nm-device-6lowpan.h index d5f8a7a5..7feba237 100644 --- a/src/libnm-client-public/nm-device-6lowpan.h +++ b/src/libnm-client-public/nm-device-6lowpan.h @@ -29,6 +29,8 @@ G_BEGIN_DECLS /** * NMDevice6Lowpan: + * + * Since: 1.14 */ typedef struct _NMDevice6Lowpan NMDevice6Lowpan; typedef struct _NMDevice6LowpanClass NMDevice6LowpanClass; @@ -36,13 +38,9 @@ typedef struct _NMDevice6LowpanClass NMDevice6LowpanClass; NM_AVAILABLE_IN_1_14 GType nm_device_6lowpan_get_type(void); -NM_AVAILABLE_IN_1_14 +NM_AVAILABLE_IN_1_40_4 NMDevice *nm_device_6lowpan_get_parent(NMDevice6Lowpan *device); -NM_AVAILABLE_IN_1_14 -NM_DEPRECATED_IN_1_24_FOR(nm_device_get_hw_address) -const char *nm_device_6lowpan_get_hw_address(NMDevice6Lowpan *device); - G_END_DECLS #endif /* __NM_DEVICE_6LOWPAN_H__ */ diff --git a/src/libnm-client-public/nm-device-dummy.h b/src/libnm-client-public/nm-device-dummy.h index 8b2f7485..0e6c6fe6 100644 --- a/src/libnm-client-public/nm-device-dummy.h +++ b/src/libnm-client-public/nm-device-dummy.h @@ -28,6 +28,8 @@ G_BEGIN_DECLS /** * NMDeviceDummy: + * + * Since: 1.8 */ typedef struct _NMDeviceDummy NMDeviceDummy; typedef struct _NMDeviceDummyClass NMDeviceDummyClass; diff --git a/src/libnm-client-public/nm-device-ip-tunnel.h b/src/libnm-client-public/nm-device-ip-tunnel.h index 4f55dc0b..4b9b9f5b 100644 --- a/src/libnm-client-public/nm-device-ip-tunnel.h +++ b/src/libnm-client-public/nm-device-ip-tunnel.h @@ -41,6 +41,8 @@ G_BEGIN_DECLS /** * NMDeviceIPTunnel: + * + * Since: 1.2 */ typedef struct _NMDeviceIPTunnel NMDeviceIPTunnel; typedef struct _NMDeviceIPTunnelClass NMDeviceIPTunnelClass; diff --git a/src/libnm-client-public/nm-device-macsec.h b/src/libnm-client-public/nm-device-macsec.h index b1ec3637..f4f6f03d 100644 --- a/src/libnm-client-public/nm-device-macsec.h +++ b/src/libnm-client-public/nm-device-macsec.h @@ -41,6 +41,8 @@ G_BEGIN_DECLS /** * NMDeviceMacsec: + * + * Since: 1.6 */ typedef struct _NMDeviceMacsec NMDeviceMacsec; typedef struct _NMDeviceMacsecClass NMDeviceMacsecClass; @@ -48,7 +50,7 @@ typedef struct _NMDeviceMacsecClass NMDeviceMacsecClass; NM_AVAILABLE_IN_1_6 GType nm_device_macsec_get_type(void); -NM_AVAILABLE_IN_1_6 +NM_AVAILABLE_IN_1_40_4 NMDevice *nm_device_macsec_get_parent(NMDeviceMacsec *device); NM_AVAILABLE_IN_1_6 diff --git a/src/libnm-client-public/nm-device-macvlan.h b/src/libnm-client-public/nm-device-macvlan.h index 95699334..85292069 100644 --- a/src/libnm-client-public/nm-device-macvlan.h +++ b/src/libnm-client-public/nm-device-macvlan.h @@ -32,6 +32,8 @@ G_BEGIN_DECLS /** * NMDeviceMacvlan: + * + * Since: 1.2 */ typedef struct _NMDeviceMacvlan NMDeviceMacvlan; typedef struct _NMDeviceMacvlanClass NMDeviceMacvlanClass; diff --git a/src/libnm-client-public/nm-device-ovs-bridge.h b/src/libnm-client-public/nm-device-ovs-bridge.h index 8c454057..a6c9ff0b 100644 --- a/src/libnm-client-public/nm-device-ovs-bridge.h +++ b/src/libnm-client-public/nm-device-ovs-bridge.h @@ -29,6 +29,8 @@ G_BEGIN_DECLS /** * NMDeviceOvsBridge: + * + * Since: 1.10 */ typedef struct _NMDeviceOvsBridge NMDeviceOvsBridge; typedef struct _NMDeviceOvsBridgeClass NMDeviceOvsBridgeClass; diff --git a/src/libnm-client-public/nm-device-ovs-interface.h b/src/libnm-client-public/nm-device-ovs-interface.h index 1ba7ac3a..eb74ee48 100644 --- a/src/libnm-client-public/nm-device-ovs-interface.h +++ b/src/libnm-client-public/nm-device-ovs-interface.h @@ -28,6 +28,8 @@ G_BEGIN_DECLS /** * NMDeviceOvsInterface: + * + * Since: 1.10 */ typedef struct _NMDeviceOvsInterface NMDeviceOvsInterface; typedef struct _NMDeviceOvsInterfaceClass NMDeviceOvsInterfaceClass; diff --git a/src/libnm-client-public/nm-device-ovs-port.h b/src/libnm-client-public/nm-device-ovs-port.h index 7524cacb..8014ed91 100644 --- a/src/libnm-client-public/nm-device-ovs-port.h +++ b/src/libnm-client-public/nm-device-ovs-port.h @@ -29,6 +29,8 @@ G_BEGIN_DECLS /** * NMDeviceOvsPort: + * + * Since: 1.10 */ typedef struct _NMDeviceOvsPort NMDeviceOvsPort; typedef struct _NMDeviceOvsPortClass NMDeviceOvsPortClass; diff --git a/src/libnm-client-public/nm-device-ppp.h b/src/libnm-client-public/nm-device-ppp.h index 4003f901..4d56cd89 100644 --- a/src/libnm-client-public/nm-device-ppp.h +++ b/src/libnm-client-public/nm-device-ppp.h @@ -23,10 +23,13 @@ G_BEGIN_DECLS /** * NMDevicePpp: + * + * Since: 1.10 */ typedef struct _NMDevicePpp NMDevicePpp; typedef struct _NMDevicePppClass NMDevicePppClass; +NM_AVAILABLE_IN_1_10 GType nm_device_ppp_get_type(void); G_END_DECLS diff --git a/src/libnm-client-public/nm-device-tun.h b/src/libnm-client-public/nm-device-tun.h index e1e7310d..42690358 100644 --- a/src/libnm-client-public/nm-device-tun.h +++ b/src/libnm-client-public/nm-device-tun.h @@ -33,6 +33,8 @@ G_BEGIN_DECLS /** * NMDeviceTun: + * + * Since: 1.2 */ typedef struct _NMDeviceTun NMDeviceTun; typedef struct _NMDeviceTunClass NMDeviceTunClass; diff --git a/src/libnm-client-public/nm-device-veth.h b/src/libnm-client-public/nm-device-veth.h index 8f61ae20..9de27595 100644 --- a/src/libnm-client-public/nm-device-veth.h +++ b/src/libnm-client-public/nm-device-veth.h @@ -27,6 +27,8 @@ G_BEGIN_DECLS /** * NMDeviceVeth: + * + * Since: 1.30 */ typedef struct _NMDeviceVeth NMDeviceVeth; typedef struct _NMDeviceVethClass NMDeviceVethClass; @@ -34,7 +36,7 @@ typedef struct _NMDeviceVethClass NMDeviceVethClass; NM_AVAILABLE_IN_1_30 GType nm_device_veth_get_type(void); -NM_AVAILABLE_IN_1_30 +NM_AVAILABLE_IN_1_40_4 NMDevice *nm_device_veth_get_peer(NMDeviceVeth *device); G_END_DECLS diff --git a/src/libnm-client-public/nm-device-vrf.h b/src/libnm-client-public/nm-device-vrf.h index fbc8b202..82e0657d 100644 --- a/src/libnm-client-public/nm-device-vrf.h +++ b/src/libnm-client-public/nm-device-vrf.h @@ -24,6 +24,8 @@ G_BEGIN_DECLS /** * NMDeviceVrf: + * + * Since: 1.24 */ typedef struct _NMDeviceVrf NMDeviceVrf; typedef struct _NMDeviceVrfClass NMDeviceVrfClass; diff --git a/src/libnm-client-public/nm-device-vxlan.h b/src/libnm-client-public/nm-device-vxlan.h index 7939539d..fa7511e1 100644 --- a/src/libnm-client-public/nm-device-vxlan.h +++ b/src/libnm-client-public/nm-device-vxlan.h @@ -45,6 +45,8 @@ G_BEGIN_DECLS /** * NMDeviceVxlan: + * + * Since: 1.2 */ typedef struct _NMDeviceVxlan NMDeviceVxlan; typedef struct _NMDeviceVxlanClass NMDeviceVxlanClass; @@ -56,7 +58,7 @@ NM_AVAILABLE_IN_1_2 NM_DEPRECATED_IN_1_24_FOR(nm_device_get_hw_address) const char *nm_device_vxlan_get_hw_address(NMDeviceVxlan *device); -NM_AVAILABLE_IN_1_2 +NM_AVAILABLE_IN_1_40_4 gboolean nm_device_vxlan_get_carrier(NMDeviceVxlan *device); NM_AVAILABLE_IN_1_2 NMDevice *nm_device_vxlan_get_parent(NMDeviceVxlan *device); @@ -84,7 +86,7 @@ NM_AVAILABLE_IN_1_2 guint nm_device_vxlan_get_limit(NMDeviceVxlan *device); NM_AVAILABLE_IN_1_2 gboolean nm_device_vxlan_get_proxy(NMDeviceVxlan *device); -NM_AVAILABLE_IN_1_2 +NM_AVAILABLE_IN_1_40_4 gboolean nm_device_vxlan_get_rsc(NMDeviceVxlan *device); NM_AVAILABLE_IN_1_2 gboolean nm_device_vxlan_get_l2miss(NMDeviceVxlan *device); diff --git a/src/libnm-client-public/nm-device-wifi-p2p.h b/src/libnm-client-public/nm-device-wifi-p2p.h index ad0ca436..31add1e3 100644 --- a/src/libnm-client-public/nm-device-wifi-p2p.h +++ b/src/libnm-client-public/nm-device-wifi-p2p.h @@ -44,7 +44,7 @@ NM_AVAILABLE_IN_1_16 NM_DEPRECATED_IN_1_24_FOR(nm_device_get_hw_address) const char *nm_device_wifi_p2p_get_hw_address(NMDeviceWifiP2P *device); -NM_AVAILABLE_IN_1_16 +NM_AVAILABLE_IN_1_40_4 NMWifiP2PPeer *nm_device_wifi_p2p_get_peer_by_path(NMDeviceWifiP2P *device, const char *path); NM_AVAILABLE_IN_1_16 diff --git a/src/libnm-client-public/nm-device-wireguard.h b/src/libnm-client-public/nm-device-wireguard.h index 756dfb4e..fa167878 100644 --- a/src/libnm-client-public/nm-device-wireguard.h +++ b/src/libnm-client-public/nm-device-wireguard.h @@ -27,6 +27,8 @@ G_BEGIN_DECLS /** * NMDeviceWireGuard: + * + * Since: 1.14 */ typedef struct _NMDeviceWireGuard NMDeviceWireGuard; typedef struct _NMDeviceWireGuardClass NMDeviceWireGuardClass; diff --git a/src/libnm-client-public/nm-device-wpan.h b/src/libnm-client-public/nm-device-wpan.h index 8b011851..d6805040 100644 --- a/src/libnm-client-public/nm-device-wpan.h +++ b/src/libnm-client-public/nm-device-wpan.h @@ -27,6 +27,8 @@ G_BEGIN_DECLS /** * NMDeviceWpan: + * + * Since: 1.14 */ typedef struct _NMDeviceWpan NMDeviceWpan; typedef struct _NMDeviceWpanClass NMDeviceWpanClass; @@ -34,10 +36,6 @@ typedef struct _NMDeviceWpanClass NMDeviceWpanClass; NM_AVAILABLE_IN_1_14 GType nm_device_wpan_get_type(void); -NM_AVAILABLE_IN_1_14 -NM_DEPRECATED_IN_1_24_FOR(nm_device_get_hw_address) -const char *nm_device_wpan_get_hw_address(NMDeviceWpan *device); - G_END_DECLS #endif /* __NM_DEVICE_WPAN_H__ */ diff --git a/src/libnm-client-public/nm-vpn-plugin-old.h b/src/libnm-client-public/nm-vpn-plugin-old.h index fe0d4bc2..cc6f6178 100644 --- a/src/libnm-client-public/nm-vpn-plugin-old.h +++ b/src/libnm-client-public/nm-vpn-plugin-old.h @@ -108,15 +108,9 @@ NM_DEPRECATED_IN_1_2 void nm_vpn_plugin_old_failure(NMVpnPluginOld *plugin, NMVpnPluginFailure reason); NM_DEPRECATED_IN_1_2 -void nm_vpn_plugin_old_set_config(NMVpnPluginOld *plugin, GVariant *config); - -NM_DEPRECATED_IN_1_2 void nm_vpn_plugin_old_set_ip4_config(NMVpnPluginOld *plugin, GVariant *ip4_config); NM_DEPRECATED_IN_1_2 -void nm_vpn_plugin_old_set_ip6_config(NMVpnPluginOld *plugin, GVariant *ip6_config); - -NM_DEPRECATED_IN_1_2 gboolean nm_vpn_plugin_old_disconnect(NMVpnPluginOld *plugin, GError **err); /* Utility functions */ diff --git a/src/libnm-client-public/nm-vpn-service-plugin.h b/src/libnm-client-public/nm-vpn-service-plugin.h index 5187d93d..baf5b3a6 100644 --- a/src/libnm-client-public/nm-vpn-service-plugin.h +++ b/src/libnm-client-public/nm-vpn-service-plugin.h @@ -35,6 +35,8 @@ G_BEGIN_DECLS /** * NMVpnServicePlugin: + * + * Since: 1.2 */ typedef struct { NM_AVAILABLE_IN_1_2 diff --git a/src/libnm-client-public/nm-wifi-p2p-peer.h b/src/libnm-client-public/nm-wifi-p2p-peer.h index eff27bcb..dd8a109f 100644 --- a/src/libnm-client-public/nm-wifi-p2p-peer.h +++ b/src/libnm-client-public/nm-wifi-p2p-peer.h @@ -37,6 +37,8 @@ G_BEGIN_DECLS /** * NMWifiP2PPeer: + * + * Since: 1.16 */ typedef struct _NMWifiP2PPeer NMWifiP2PPeer; typedef struct _NMWifiP2PPeerClass NMWifiP2PPeerClass; diff --git a/src/libnm-core-impl/nm-connection.c b/src/libnm-core-impl/nm-connection.c index aed4be21..2f5bf357 100644 --- a/src/libnm-core-impl/nm-connection.c +++ b/src/libnm-core-impl/nm-connection.c @@ -228,8 +228,10 @@ _nm_connection_add_setting(NMConnection *connection, NMSetting *setting) priv = NM_CONNECTION_GET_PRIVATE(connection); s_old = priv->settings[setting_info->meta_type]; - if (s_old == setting) + if (s_old == setting) { + g_object_unref(s_old); return; + } priv->settings[setting_info->meta_type] = setting; @@ -3487,7 +3489,7 @@ nm_connection_get_setting_olpc_mesh(NMConnection *connection) * * Returns: (transfer none): an #NMSettingOvsBridge if the connection contains one, otherwise %NULL * - * Since: 1.10 + * Since: 1.14 **/ NMSettingOvsBridge * nm_connection_get_setting_ovs_bridge(NMConnection *connection) @@ -3503,7 +3505,7 @@ nm_connection_get_setting_ovs_bridge(NMConnection *connection) * * Returns: (transfer none): an #NMSettingOvsInterface if the connection contains one, otherwise %NULL * - * Since: 1.10 + * Since: 1.14 **/ NMSettingOvsInterface * nm_connection_get_setting_ovs_interface(NMConnection *connection) @@ -3520,7 +3522,7 @@ nm_connection_get_setting_ovs_interface(NMConnection *connection) * * Returns: (transfer none): an #NMSettingOvsPatch if the connection contains one, otherwise %NULL * - * Since: 1.10 + * Since: 1.14 **/ NMSettingOvsPatch * nm_connection_get_setting_ovs_patch(NMConnection *connection) @@ -3536,7 +3538,7 @@ nm_connection_get_setting_ovs_patch(NMConnection *connection) * * Returns: (transfer none): an #NMSettingOvsPort if the connection contains one, otherwise %NULL * - * Since: 1.10 + * Since: 1.14 **/ NMSettingOvsPort * nm_connection_get_setting_ovs_port(NMConnection *connection) @@ -3626,7 +3628,7 @@ nm_connection_get_setting_tc_config(NMConnection *connection) * * Returns: (transfer none): an #NMSettingTun if the connection contains one, otherwise %NULL * - * Since: 1.2 + * Since: 1.14 **/ NMSettingTun * nm_connection_get_setting_tun(NMConnection *connection) diff --git a/src/libnm-core-impl/nm-setting-6lowpan.c b/src/libnm-core-impl/nm-setting-6lowpan.c index 765af69b..21b3dbb9 100644 --- a/src/libnm-core-impl/nm-setting-6lowpan.c +++ b/src/libnm-core-impl/nm-setting-6lowpan.c @@ -29,6 +29,8 @@ typedef struct { * NMSetting6Lowpan: * * 6LoWPAN Settings + * + * Since: 1.14 */ struct _NMSetting6Lowpan { NMSetting parent; @@ -51,7 +53,7 @@ G_DEFINE_TYPE(NMSetting6Lowpan, nm_setting_6lowpan, NM_TYPE_SETTING) * * Returns: the #NMSetting6Lowpan:parent property of the setting * - * Since: 1.14 + * Since: 1.42, 1.40.4 **/ const char * nm_setting_6lowpan_get_parent(NMSetting6Lowpan *setting) @@ -139,7 +141,7 @@ nm_setting_6lowpan_init(NMSetting6Lowpan *setting) * * Returns: (transfer full): the new empty #NMSetting6Lowpan object * - * Since: 1.14 + * Since: 1.42, 1.40.4 **/ NMSetting * nm_setting_6lowpan_new(void) diff --git a/src/libnm-core-impl/nm-setting-bond-port.c b/src/libnm-core-impl/nm-setting-bond-port.c index 9b41a74f..7ea82a76 100644 --- a/src/libnm-core-impl/nm-setting-bond-port.c +++ b/src/libnm-core-impl/nm-setting-bond-port.c @@ -85,13 +85,15 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) } slave_type = nm_setting_connection_get_slave_type(s_con); - if (!nm_streq0(slave_type, NM_SETTING_BOND_SETTING_NAME)) { + if (slave_type && !nm_streq(slave_type, NM_SETTING_BOND_SETTING_NAME)) { g_set_error(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("A connection with a '%s' setting must have the slave-type set to '%s'"), + _("A connection with a '%s' setting must have the slave-type set to '%s'. " + "Instead it is '%s'"), NM_SETTING_BOND_PORT_SETTING_NAME, - NM_SETTING_BOND_SETTING_NAME); + NM_SETTING_BOND_SETTING_NAME, + slave_type); g_prefix_error(error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, diff --git a/src/libnm-core-impl/nm-setting-bond.c b/src/libnm-core-impl/nm-setting-bond.c index cdfc7641..18b6fefb 100644 --- a/src/libnm-core-impl/nm-setting-bond.c +++ b/src/libnm-core-impl/nm-setting-bond.c @@ -764,37 +764,64 @@ _nm_setting_bond_get_option_type(NMSettingBond *setting, const char *name) return option_meta->opt_type; } -guint32 -_nm_setting_bond_opt_value_as_u32(NMSettingBond *s_bond, const char *opt) +#define _opt_value_as_u64(s_bond, opt, v_max) \ + ({ \ + const OptionMeta *_meta; \ + NMSettingBond *_s_bond = (s_bond); \ + const char *_opt = (opt); \ + const guint64 _v_max = (v_max); \ + const char *_s; \ + guint64 _val; \ + \ + nm_assert(NM_IS_SETTING_BOND(_s_bond)); \ + nm_assert(_opt); \ + \ + _meta = _get_option_meta(_opt); \ + \ + nm_assert(_meta); \ + nm_assert(_meta->opt_type == NM_BOND_OPTION_TYPE_INT); \ + nm_assert(_meta->min < _meta->max); \ + nm_assert(_meta->max <= _v_max); \ + nm_assert(_meta->val); \ + \ + _s = nm_setting_bond_get_option_normalized(_s_bond, _opt); \ + if (_s) { \ + _val = _nm_utils_ascii_str_to_uint64(_s, 10, _meta->min, _meta->max, 0); \ + /* Note that _s is only a valid integer, if the profile verifies. We require + * that the caller only calls these functions on valid profile. */ \ + nm_assert(errno == 0); \ + } else { \ + _val = 0; \ + errno = EINVAL; \ + } \ + \ + _val; \ + }) + +guint8 +_nm_setting_bond_opt_value_as_u8(NMSettingBond *s_bond, const char *opt) { - nm_assert(_get_option_meta(opt)->opt_type == NM_BOND_OPTION_TYPE_INT); - return _nm_utils_ascii_str_to_uint64(nm_setting_bond_get_option_normalized(s_bond, opt), - 10, - 0, - G_MAXUINT32, - 0); + return _opt_value_as_u64(s_bond, opt, G_MAXUINT8); } guint16 _nm_setting_bond_opt_value_as_u16(NMSettingBond *s_bond, const char *opt) { - nm_assert(_get_option_meta(opt)->opt_type == NM_BOND_OPTION_TYPE_INT); - return _nm_utils_ascii_str_to_uint64(nm_setting_bond_get_option_normalized(s_bond, opt), - 10, - 0, - G_MAXUINT16, - 0); + return _opt_value_as_u64(s_bond, opt, G_MAXUINT16); } -guint8 -_nm_setting_bond_opt_value_as_u8(NMSettingBond *s_bond, const char *opt) +guint32 +_nm_setting_bond_opt_value_as_u32(NMSettingBond *s_bond, const char *opt) +{ + return _opt_value_as_u64(s_bond, opt, G_MAXUINT32); +} + +bool +_nm_setting_bond_opt_value_as_intbool(NMSettingBond *s_bond, const char *opt) { - nm_assert(_get_option_meta(opt)->opt_type == NM_BOND_OPTION_TYPE_INT); - return _nm_utils_ascii_str_to_uint64(nm_setting_bond_get_option_normalized(s_bond, opt), - 10, - 0, - G_MAXUINT8, - 0); + /* This does not parse the value as a boolean string, instead, it requires + * that it's a number, either "0" or "1". */ + return _opt_value_as_u64(s_bond, opt, 1); } /*****************************************************************************/ diff --git a/src/libnm-core-impl/nm-setting-bridge.c b/src/libnm-core-impl/nm-setting-bridge.c index 39a3fb60..89611147 100644 --- a/src/libnm-core-impl/nm-setting-bridge.c +++ b/src/libnm-core-impl/nm-setting-bridge.c @@ -926,7 +926,7 @@ _nm_setting_bridge_get_vlans(NMSettingBridge *setting) * * Returns: the #NMSettingBridge:group-address property of the setting * - * Since 1.24 + * Since: 1.24 **/ const char * nm_setting_bridge_get_group_address(const NMSettingBridge *setting) @@ -942,7 +942,7 @@ nm_setting_bridge_get_group_address(const NMSettingBridge *setting) * * Returns: the #NMSettingBridge:vlan-protocol property of the setting * - * Since 1.24 + * Since: 1.24 **/ const char * nm_setting_bridge_get_vlan_protocol(const NMSettingBridge *setting) @@ -958,7 +958,7 @@ nm_setting_bridge_get_vlan_protocol(const NMSettingBridge *setting) * * Returns: the #NMSettingBridge:vlan-stats-enabled property of the setting * - * Since 1.24 + * Since: 1.24 **/ gboolean nm_setting_bridge_get_vlan_stats_enabled(const NMSettingBridge *setting) @@ -974,7 +974,7 @@ nm_setting_bridge_get_vlan_stats_enabled(const NMSettingBridge *setting) * * Returns: the #NMSettingBridge:multicast-router property of the setting * - * Since 1.24 + * Since: 1.24 **/ const char * nm_setting_bridge_get_multicast_router(const NMSettingBridge *setting) @@ -990,7 +990,7 @@ nm_setting_bridge_get_multicast_router(const NMSettingBridge *setting) * * Returns: the #NMSettingBridge:multicast-query-use-ifaddr property of the setting * - * Since 1.24 + * Since: 1.24 **/ gboolean nm_setting_bridge_get_multicast_query_use_ifaddr(const NMSettingBridge *setting) @@ -1006,7 +1006,7 @@ nm_setting_bridge_get_multicast_query_use_ifaddr(const NMSettingBridge *setting) * * Returns: the #NMSettingBridge:multicast-querier property of the setting * - * Since 1.24 + * Since: 1.24 **/ gboolean nm_setting_bridge_get_multicast_querier(const NMSettingBridge *setting) @@ -1022,7 +1022,7 @@ nm_setting_bridge_get_multicast_querier(const NMSettingBridge *setting) * * Returns: the #NMSettingBridge:multicast-hash-max property of the setting * - * Since 1.26 + * Since: 1.26 **/ guint32 nm_setting_bridge_get_multicast_hash_max(const NMSettingBridge *setting) @@ -1038,7 +1038,7 @@ nm_setting_bridge_get_multicast_hash_max(const NMSettingBridge *setting) * * Returns: the #NMSettingBridge:multicast-last-member-count property of the setting * - * Since 1.26 + * Since: 1.26 **/ guint32 nm_setting_bridge_get_multicast_last_member_count(const NMSettingBridge *setting) @@ -1054,7 +1054,7 @@ nm_setting_bridge_get_multicast_last_member_count(const NMSettingBridge *setting * * Returns: the #NMSettingBridge:multicast-last-member-interval property of the setting * - * Since 1.26 + * Since: 1.26 **/ guint64 nm_setting_bridge_get_multicast_last_member_interval(const NMSettingBridge *setting) @@ -1070,7 +1070,7 @@ nm_setting_bridge_get_multicast_last_member_interval(const NMSettingBridge *sett * * Returns: the #NMSettingBridge:multicast-membership-interval property of the setting * - * Since 1.26 + * Since: 1.26 **/ guint64 nm_setting_bridge_get_multicast_membership_interval(const NMSettingBridge *setting) @@ -1086,7 +1086,7 @@ nm_setting_bridge_get_multicast_membership_interval(const NMSettingBridge *setti * * Returns: the #NMSettingBridge:multicast-querier-interval property of the setting * - * Since 1.26 + * Since: 1.26 **/ guint64 nm_setting_bridge_get_multicast_querier_interval(const NMSettingBridge *setting) @@ -1102,7 +1102,7 @@ nm_setting_bridge_get_multicast_querier_interval(const NMSettingBridge *setting) * * Returns: the #NMSettingBridge:multicast-query-interval property of the setting * - * Since 1.26 + * Since: 1.26 **/ guint64 nm_setting_bridge_get_multicast_query_interval(const NMSettingBridge *setting) @@ -1118,7 +1118,7 @@ nm_setting_bridge_get_multicast_query_interval(const NMSettingBridge *setting) * * Returns: the #NMSettingBridge:multicast-query-response-interval property of the setting * - * Since 1.26 + * Since: 1.26 **/ guint64 nm_setting_bridge_get_multicast_query_response_interval(const NMSettingBridge *setting) @@ -1134,7 +1134,7 @@ nm_setting_bridge_get_multicast_query_response_interval(const NMSettingBridge *s * * Returns: the #NMSettingBridge:multicast-query-response-interval property of the setting * - * Since 1.26 + * Since: 1.26 **/ guint32 nm_setting_bridge_get_multicast_startup_query_count(const NMSettingBridge *setting) @@ -1150,7 +1150,7 @@ nm_setting_bridge_get_multicast_startup_query_count(const NMSettingBridge *setti * * Returns: the #NMSettingBridge:multicast-startup-query-interval property of the setting * - * Since 1.26 + * Since: 1.26 **/ guint64 nm_setting_bridge_get_multicast_startup_query_interval(const NMSettingBridge *setting) diff --git a/src/libnm-core-impl/nm-setting-connection.c b/src/libnm-core-impl/nm-setting-connection.c index cbce1c12..bc14c767 100644 --- a/src/libnm-core-impl/nm-setting-connection.c +++ b/src/libnm-core-impl/nm-setting-connection.c @@ -1023,7 +1023,7 @@ nm_setting_connection_get_dns_over_tls(NMSettingConnection *setting) * * Returns: the #NMSettingConnection:mptcp-flags property of the setting. * - * Since: 1.40 + * Since: 1.42, 1.40.4 **/ NMMptcpFlags nm_setting_connection_get_mptcp_flags(NMSettingConnection *setting) diff --git a/src/libnm-core-impl/nm-setting-ethtool.c b/src/libnm-core-impl/nm-setting-ethtool.c index 71179efd..1db6c335 100644 --- a/src/libnm-core-impl/nm-setting-ethtool.c +++ b/src/libnm-core-impl/nm-setting-ethtool.c @@ -23,20 +23,6 @@ /*****************************************************************************/ -static const GVariantType * -get_variant_type_from_ethtool_id(NMEthtoolID ethtool_id) -{ - if (nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id)) - return G_VARIANT_TYPE_BOOLEAN; - - if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id)) - return G_VARIANT_TYPE_UINT32; - - return NULL; -} - -/*****************************************************************************/ - /** * nm_ethtool_optname_is_feature: * @optname: (allow-none): the option name to check @@ -302,7 +288,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) NMEthtoolID ethtool_id; ethtool_id = nm_ethtool_id_get_by_name(optname); - variant_type = get_variant_type_from_ethtool_id(ethtool_id); + variant_type = nm_ethtool_id_get_variant_type(ethtool_id); if (!variant_type) { g_set_error_literal(error, @@ -365,7 +351,7 @@ get_variant_type(const NMSettInfoSetting *sett_info, const char *name, GError ** { const GVariantType *variant_type; - variant_type = get_variant_type_from_ethtool_id(nm_ethtool_id_get_by_name(name)); + variant_type = nm_ethtool_id_get_variant_type(nm_ethtool_id_get_by_name(name)); if (!variant_type) { g_set_error(error, diff --git a/src/libnm-core-impl/nm-setting-hostname.c b/src/libnm-core-impl/nm-setting-hostname.c index 276a75a8..8a5e50be 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.30 + * Since: 1.42, 1.40.4 **/ NMSetting * nm_setting_hostname_new(void) diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index 916a8038..73f98ab1 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -266,6 +266,8 @@ nm_ip_address_unref(NMIPAddress *address) * * Returns: 0 if the two objects have the same values (according to their flags) * or a integer indicating the compare order. + * + * Since: 1.22 **/ int nm_ip_address_cmp_full(const NMIPAddress *a, const NMIPAddress *b, NMIPAddressCmpFlags cmp_flags) @@ -4343,6 +4345,8 @@ nm_setting_ip_config_get_num_dns_options(NMSettingIPConfig *setting) * a default configuration, while the former explicitly means "no-options". * * Returns: whether DNS options are initialized or left unset (the default). + * + * Since: 1.2 **/ gboolean nm_setting_ip_config_has_dns_options(NMSettingIPConfig *setting) @@ -5291,7 +5295,7 @@ nm_setting_ip_config_get_required_timeout(NMSettingIPConfig *setting) * * Returns: the configured DHCP IAID (Identity Association Identifier) * - * Since: 1.22 + * Since: 1.42, 1.40.4 **/ const char * nm_setting_ip_config_get_dhcp_iaid(NMSettingIPConfig *setting) diff --git a/src/libnm-core-impl/nm-setting-ip-tunnel.c b/src/libnm-core-impl/nm-setting-ip-tunnel.c index d42e97b9..73416813 100644 --- a/src/libnm-core-impl/nm-setting-ip-tunnel.c +++ b/src/libnm-core-impl/nm-setting-ip-tunnel.c @@ -240,7 +240,7 @@ nm_setting_ip_tunnel_get_output_key(NMSettingIPTunnel *setting) * * Returns: the encapsulation limit value * - * Since: 1.2 + * Since: 1.42, 1.40.4 **/ guint nm_setting_ip_tunnel_get_encapsulation_limit(NMSettingIPTunnel *setting) @@ -258,7 +258,7 @@ nm_setting_ip_tunnel_get_encapsulation_limit(NMSettingIPTunnel *setting) * * Returns: the flow label value * - * Since: 1.2 + * Since: 1.42, 1.40.4 **/ guint nm_setting_ip_tunnel_get_flow_label(NMSettingIPTunnel *setting) @@ -286,7 +286,7 @@ nm_setting_ip_tunnel_get_mtu(NMSettingIPTunnel *setting) return NM_SETTING_IP_TUNNEL_GET_PRIVATE(setting)->mtu; } -/* +/** * nm_setting_ip_tunnel_get_flags: * @setting: the #NMSettingIPTunnel * diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index ff56834e..d991152c 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.40 + * Since: 1.42, 1.40.4 **/ NMSettingIP4LinkLocal nm_setting_ip4_config_get_link_local(NMSettingIP4Config *setting) @@ -898,7 +898,7 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * a global connection default gets consulted. * If still unspecified, the DHCP option is not sent to the server. * - * Since 1.28 + * Since: 1.28 */ /* ---ifcfg-rh--- * property: dhcp-vendor-class-identifier @@ -928,7 +928,7 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass) * falling back to "auto". Note that if "ipv4.method" is "disabled", then * link local addressing is always disabled too. The default is "default". * - * Since 1.40 + * Since: 1.40 */ /* ---ifcfg-rh--- * property: link-local diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c index 8b593b97..94794d1e 100644 --- a/src/libnm-core-impl/nm-setting-ip6-config.c +++ b/src/libnm-core-impl/nm-setting-ip6-config.c @@ -832,8 +832,7 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_DEFAULT, NM_SETTING_PARAM_NONE, NMSettingIP6ConfigPrivate, - addr_gen_mode, - .to_dbus_including_default = TRUE); + addr_gen_mode); /** * NMSettingIP6Config:token: diff --git a/src/libnm-core-impl/nm-setting-ovs-bridge.c b/src/libnm-core-impl/nm-setting-ovs-bridge.c index b15aab19..7dc9fda4 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.20 + * Since: 1.42, 1.40.4 **/ const char * nm_setting_ovs_bridge_get_datapath_type(NMSettingOvsBridge *self) 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 6b8d5d37..f4e31f81 100644 --- a/src/libnm-core-impl/nm-setting-ovs-external-ids.c +++ b/src/libnm-core-impl/nm-setting-ovs-external-ids.c @@ -195,6 +195,8 @@ _nm_setting_ovs_external_ids_get_data(NMSettingOvsExternalIDs *self) * * Returns: (array length=out_len) (transfer none): a * %NULL-terminated array containing each key from the table. + * + * Since: 1.30 **/ const char *const * nm_setting_ovs_external_ids_get_data_keys(NMSettingOvsExternalIDs *setting, guint *out_len) diff --git a/src/libnm-core-impl/nm-setting-sriov.c b/src/libnm-core-impl/nm-setting-sriov.c index 30dd8f54..f9bee21e 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.14 + * Since: 1.42, 1.40.4 */ gboolean nm_sriov_vf_attribute_validate(const char *name, GVariant *value, gboolean *known, GError **error) @@ -649,7 +649,7 @@ nm_sriov_vf_get_vlan_qos(const NMSriovVF *vf, guint vlan_id) return vlan->qos; } -/* +/** * nm_sriov_vf_get_vlan_protocol: * @vf: the #NMSriovVF * @vlan_id: the VLAN id diff --git a/src/libnm-core-impl/nm-setting-tc-config.c b/src/libnm-core-impl/nm-setting-tc-config.c index 08a7f94d..529bbca1 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.12 + * Since: 1.42, 1.40.4 **/ 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.12 + * Since: 1.42, 1.40.4 **/ void nm_tc_tfilter_set_action(NMTCTfilter *tfilter, NMTCAction *action) diff --git a/src/libnm-core-impl/nm-setting-user.c b/src/libnm-core-impl/nm-setting-user.c index 0e95d38b..70bdc62a 100644 --- a/src/libnm-core-impl/nm-setting-user.c +++ b/src/libnm-core-impl/nm-setting-user.c @@ -35,6 +35,8 @@ typedef struct { * NMSettingUser: * * General User Profile Settings + * + * Since: 1.8 */ struct _NMSettingUser { NMSetting parent; @@ -216,6 +218,8 @@ _create_data_hash(void) * * Returns: (array length=out_len) (transfer none): a * %NULL-terminated array containing each key from the table. + * + * Since: 1.8 **/ const char *const * nm_setting_user_get_keys(NMSettingUser *setting, guint *out_len) @@ -498,6 +502,8 @@ nm_setting_user_init(NMSettingUser *self) * Creates a new #NMSettingUser object with default values. * * Returns: the new empty #NMSettingUser object + * + * Since: 1.8 **/ NMSetting * nm_setting_user_new(void) diff --git a/src/libnm-core-impl/nm-setting-vpn.c b/src/libnm-core-impl/nm-setting-vpn.c index 42f75fa2..7e6f18dd 100644 --- a/src/libnm-core-impl/nm-setting-vpn.c +++ b/src/libnm-core-impl/nm-setting-vpn.c @@ -147,6 +147,8 @@ nm_setting_vpn_get_user_name(NMSettingVpn *setting) * @setting: the #NMSettingVpn * * Returns: the #NMSettingVpn:persistent property of the setting + * + * Since: 1.42, 1.40.4 **/ gboolean nm_setting_vpn_get_persistent(NMSettingVpn *setting) diff --git a/src/libnm-core-impl/nm-setting-wireguard.c b/src/libnm-core-impl/nm-setting-wireguard.c index ad0f01d5..599ded3c 100644 --- a/src/libnm-core-impl/nm-setting-wireguard.c +++ b/src/libnm-core-impl/nm-setting-wireguard.c @@ -1437,7 +1437,7 @@ _peers_clear(NMSettingWireGuardPrivate *priv) } /** - * nm_setting_wireguard_: + * nm_setting_wireguard_clear_peers: * @self: the #NMSettingWireGuard instance * * Returns: the number of cleared peers. diff --git a/src/libnm-core-impl/nm-setting-wireless-security.c b/src/libnm-core-impl/nm-setting-wireless-security.c index d9c5afb8..ebefd504 100644 --- a/src/libnm-core-impl/nm-setting-wireless-security.c +++ b/src/libnm-core-impl/nm-setting-wireless-security.c @@ -561,7 +561,7 @@ nm_setting_wireless_security_clear_groups(NMSettingWirelessSecurity *setting) _notify(setting, PROP_GROUP); } -/* +/** * nm_setting_wireless_security_get_pmf: * @setting: the #NMSettingWirelessSecurity * @@ -798,7 +798,7 @@ nm_setting_wireless_security_get_wps_method(NMSettingWirelessSecurity *setting) return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(setting)->wps_method; } -/* +/** * nm_setting_wireless_security_get_fils: * @setting: the #NMSettingWirelessSecurity * diff --git a/src/libnm-core-impl/nm-setting-wpan.c b/src/libnm-core-impl/nm-setting-wpan.c index 9e25dd16..a3e56ded 100644 --- a/src/libnm-core-impl/nm-setting-wpan.c +++ b/src/libnm-core-impl/nm-setting-wpan.c @@ -53,6 +53,8 @@ typedef struct { * NMSettingWpan: * * IEEE 802.15.4 (WPAN) MAC Settings + * + * Since: 1.14 */ struct _NMSettingWpan { NMSetting parent; @@ -75,7 +77,7 @@ G_DEFINE_TYPE(NMSettingWpan, nm_setting_wpan, NM_TYPE_SETTING) * * Returns: the #NMSettingWpan:mac-address property of the setting * - * Since: 1.14 + * Since: 1.42, 1.40.4 **/ const char * nm_setting_wpan_get_mac_address(NMSettingWpan *setting) @@ -91,7 +93,7 @@ nm_setting_wpan_get_mac_address(NMSettingWpan *setting) * * Returns: the #NMSettingWpan:pan-id property of the setting * - * Since: 1.14 + * Since: 1.42, 1.40.4 **/ guint16 nm_setting_wpan_get_pan_id(NMSettingWpan *setting) @@ -107,7 +109,7 @@ nm_setting_wpan_get_pan_id(NMSettingWpan *setting) * * Returns: the #NMSettingWpan:short-address property of the setting * - * Since: 1.14 + * Since: 1.42, 1.40.4 **/ guint16 nm_setting_wpan_get_short_address(NMSettingWpan *setting) @@ -123,7 +125,7 @@ nm_setting_wpan_get_short_address(NMSettingWpan *setting) * * Returns: the #NMSettingWpan:page property of the setting * - * Since: 1.16 + * Since: 1.42, 1.40.4 **/ gint16 nm_setting_wpan_get_page(NMSettingWpan *setting) @@ -139,7 +141,7 @@ nm_setting_wpan_get_page(NMSettingWpan *setting) * * Returns: the #NMSettingWpan:channel property of the setting * - * Since: 1.16 + * Since: 1.42, 1.40.4 **/ gint16 nm_setting_wpan_get_channel(NMSettingWpan *setting) @@ -211,7 +213,7 @@ nm_setting_wpan_init(NMSettingWpan *setting) * * Returns: (transfer full): the new empty #NMSettingWpan object * - * Since: 1.14 + * Since: 1.42, 1.40.4 **/ 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 35070bae..b6f72137 100644 --- a/src/libnm-core-impl/nm-setting.c +++ b/src/libnm-core-impl/nm-setting.c @@ -30,6 +30,20 @@ /*****************************************************************************/ +/* + * We use literal numbers in the header (as opposed to e.g. + * (1 << (1 + G_PARAM_USER_SHIFT))), because g-ir-scanner sometimes gets + * confused by unknown tokens and silently treats them as zero: + * https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/366 + */ + +G_STATIC_ASSERT(G_PARAM_USER_SHIFT == 8); +G_STATIC_ASSERT(NM_SETTING_PARAM_REQUIRED == (1 << (1 + G_PARAM_USER_SHIFT))); +G_STATIC_ASSERT(NM_SETTING_PARAM_SECRET == (1 << (2 + G_PARAM_USER_SHIFT))); +G_STATIC_ASSERT(NM_SETTING_PARAM_FUZZY_IGNORE == (1 << (3 + G_PARAM_USER_SHIFT))); + +/*****************************************************************************/ + typedef struct { GHashTable *hash; const char **names; @@ -3847,7 +3861,7 @@ nm_setting_option_clear_by_name(NMSetting *setting, NMUtilsPredicateStr predicat * Returns: (transfer none): the #GVariant or %NULL if the option * is not set. * - * Since: 1.26. + * Since: 1.26 */ GVariant * nm_setting_option_get(NMSetting *setting, const char *opt_name) diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c index 3c4cbc65..1c6d36c2 100644 --- a/src/libnm-core-impl/nm-utils.c +++ b/src/libnm-core-impl/nm-utils.c @@ -147,7 +147,7 @@ nm_sock_addr_endpoint_new(const char *endpoint) gsize i; gs_free char *host_clone = NULL; const char *host; - guint16 port; + guint16 port = 0; g_return_val_if_fail(endpoint, NULL); @@ -1942,6 +1942,8 @@ next: * include additional attributes. * * Returns: (transfer none): a new floating #GVariant representing @addresses. + * + * Since: 1.42, 1.40.4 **/ GVariant * nm_utils_ip_addresses_to_variant(GPtrArray *addresses) @@ -1995,6 +1997,8 @@ 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 **/ GPtrArray * nm_utils_ip_addresses_from_variant(GVariant *value, int family) @@ -2054,6 +2058,8 @@ nm_utils_ip_addresses_from_variant(GVariant *value, int family) * prefix, next hop, metric, and additional attributes). * * Returns: (transfer none): a new floating #GVariant representing @routes. + * + * Since: 1.42, 1.40.4 **/ GVariant * nm_utils_ip_routes_to_variant(GPtrArray *routes) @@ -2120,6 +2126,8 @@ 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 **/ GPtrArray * nm_utils_ip_routes_from_variant(GVariant *value, int family) @@ -4314,6 +4322,8 @@ nm_utils_is_valid_iface_name_utf8safe(const char *utf8safe_name) * * Before 1.20, this function did not accept %NULL as @name argument. If you * want to run against older versions of libnm, don't pass %NULL. + * + * Since: 1.6 */ gboolean nm_utils_is_valid_iface_name(const char *name, GError **error) @@ -5249,7 +5259,7 @@ next: return g_steal_pointer(&ht); } -/* +/** * nm_utils_format_variant_attributes: * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values * @attr_separator: the attribute separator character @@ -5275,8 +5285,8 @@ nm_utils_format_variant_attributes(GHashTable *attributes, /*****************************************************************************/ -/* - * nm_utils_get_timestamp_msec(): +/** + * nm_utils_get_timestamp_msec: * * Gets current time in milliseconds of CLOCK_BOOTTIME. * @@ -5314,7 +5324,7 @@ nm_utils_get_timestamp_msec(void) * Returns: the version ID of the libnm version. That is, the %NM_VERSION * at runtime. * - * Since: 1.6.0 + * Since: 1.6 */ guint nm_utils_version(void) diff --git a/src/libnm-core-impl/nm-vpn-editor-plugin.c b/src/libnm-core-impl/nm-vpn-editor-plugin.c index 225f25ef..3a6abbc2 100644 --- a/src/libnm-core-impl/nm-vpn-editor-plugin.c +++ b/src/libnm-core-impl/nm-vpn-editor-plugin.c @@ -470,8 +470,20 @@ nm_vpn_editor_plugin_import(NMVpnEditorPlugin *plugin, const char *path, GError g_return_val_if_fail(NM_IS_VPN_EDITOR_PLUGIN(plugin), NULL); if (nm_vpn_editor_plugin_get_capabilities(plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) { + gs_free_error GError *error2 = NULL; + g_return_val_if_fail(NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->import_from_file != NULL, NULL); + + if (!error) { + /* Some VPN plugins crash if error argument is omitted. Work around that + * in libnm by always requesting an error. + * + * https://gitlab.gnome.org/GNOME/NetworkManager-vpnc/-/blob/c7d197477c94c5bae0396f0ef826db4d835e487d/properties/nm-vpnc-editor-plugin.c#L281 + **/ + error = &error2; + } + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(plugin)->import_from_file(plugin, path, error); } diff --git a/src/libnm-core-impl/nm-vpn-plugin-info.c b/src/libnm-core-impl/nm-vpn-plugin-info.c index 473063fb..baa19347 100644 --- a/src/libnm-core-impl/nm-vpn-plugin-info.c +++ b/src/libnm-core-impl/nm-vpn-plugin-info.c @@ -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.2 + * Since: 1.42, 1.40.4 */ 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 64b3dca7..a21f50db 100644 --- a/src/libnm-core-impl/tests/test-general.c +++ b/src/libnm-core-impl/tests/test-general.c @@ -3139,6 +3139,9 @@ test_setting_new_from_dbus_bad(void) NULL); nm_connection_add_setting(conn, setting); + /* Test assignment of same setting again. */ + nm_connection_add_setting(conn, g_object_ref(setting)); + setting = nm_setting_wireless_new(); ssid = g_bytes_new("my-ssid", 7); g_object_set(setting, diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c index 5bdae716..a4e3932a 100644 --- a/src/libnm-core-impl/tests/test-setting.c +++ b/src/libnm-core-impl/tests/test-setting.c @@ -5068,6 +5068,65 @@ test_6lowpan_1(void) /*****************************************************************************/ +static void +test_bond_meta(void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingBond *set; + char sbuf[200]; + + create_bond_connection(&con, &set); + + g_assert_cmpstr(nm_setting_bond_get_option_normalized(set, NM_SETTING_BOND_OPTION_MODE), + ==, + "balance-rr"); + +#define _A(_nm_setting_bond_opt_value_as_xxx, set, opt, value, errsv) \ + G_STMT_START \ + { \ + g_assert_cmpint(_nm_setting_bond_opt_value_as_xxx((set), (opt)), ==, (value)); \ + g_assert_cmpint(errno, ==, (errsv)); \ + } \ + G_STMT_END + + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_MIIMON, 100, 0); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_UPDELAY, 0, 0); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_DOWNDELAY, 0, 0); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_ARP_INTERVAL, 0, 0); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_RESEND_IGMP, 1, 0); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_MIN_LINKS, 0, 0); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_LP_INTERVAL, 1, 0); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, 1, 0); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY, 0, 0); + _A(_nm_setting_bond_opt_value_as_u16, set, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, 0, EINVAL); + _A(_nm_setting_bond_opt_value_as_u16, set, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, 0, EINVAL); + _A(_nm_setting_bond_opt_value_as_u8, set, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, 1, 0); + _A(_nm_setting_bond_opt_value_as_u8, set, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE, 0, 0); + _A(_nm_setting_bond_opt_value_as_intbool, set, NM_SETTING_BOND_OPTION_USE_CARRIER, 1, 0); + _A(_nm_setting_bond_opt_value_as_intbool, + set, + NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, + 0, + EINVAL); + + nm_setting_bond_add_option(set, NM_SETTING_BOND_OPTION_ARP_INTERVAL, "5"); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_ARP_INTERVAL, 5, 0); + + nm_setting_bond_add_option(set, + NM_SETTING_BOND_OPTION_ARP_INTERVAL, + nm_sprintf_buf(sbuf, "%d", G_MAXINT)); + _A(_nm_setting_bond_opt_value_as_u32, set, NM_SETTING_BOND_OPTION_ARP_INTERVAL, G_MAXINT, 0); + + nm_setting_bond_add_option(set, NM_SETTING_BOND_OPTION_MODE, "802.3ad"); + _A(_nm_setting_bond_opt_value_as_u16, set, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO, 65535, 0); + _A(_nm_setting_bond_opt_value_as_u16, set, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, 0, 0); + + nm_setting_bond_add_option(set, NM_SETTING_BOND_OPTION_MODE, "balance-tlb"); + _A(_nm_setting_bond_opt_value_as_intbool, set, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, 1, 0); +} + +/*****************************************************************************/ + NMTST_DEFINE(); int @@ -5185,5 +5244,7 @@ main(int argc, char **argv) g_test_add_func("/libnm/test_setting_metadata", test_setting_metadata); + g_test_add_func("/libnm/test_bond_meta", test_bond_meta); + return g_test_run(); } diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h index ee4cc25b..4e1bab47 100644 --- a/src/libnm-core-intern/nm-core-internal.h +++ b/src/libnm-core-intern/nm-core-internal.h @@ -517,9 +517,10 @@ NMConnectionMultiConnect _nm_connection_get_multi_connect(NMConnection *connecti gboolean _nm_setting_bond_option_supported(const char *option, NMBondMode mode); -guint32 _nm_setting_bond_opt_value_as_u32(NMSettingBond *s_bond, const char *opt); -guint16 _nm_setting_bond_opt_value_as_u16(NMSettingBond *s_bond, const char *opt); guint8 _nm_setting_bond_opt_value_as_u8(NMSettingBond *s_bond, const char *opt); +guint16 _nm_setting_bond_opt_value_as_u16(NMSettingBond *s_bond, const char *opt); +guint32 _nm_setting_bond_opt_value_as_u32(NMSettingBond *s_bond, const char *opt); +bool _nm_setting_bond_opt_value_as_intbool(NMSettingBond *s_bond, const char *opt); /*****************************************************************************/ diff --git a/src/libnm-core-public/nm-connection.h b/src/libnm-core-public/nm-connection.h index 93061f25..47004ce8 100644 --- a/src/libnm-core-public/nm-connection.h +++ b/src/libnm-core-public/nm-connection.h @@ -220,12 +220,13 @@ NMSettingMacsec *nm_connection_get_setting_macsec(NMConnection *connection); NM_AVAILABLE_IN_1_2 NMSettingMacvlan *nm_connection_get_setting_macvlan(NMConnection *connection); NMSettingOlpcMesh *nm_connection_get_setting_olpc_mesh(NMConnection *connection); -NM_AVAILABLE_IN_1_10 +NM_AVAILABLE_IN_1_14 NMSettingOvsBridge *nm_connection_get_setting_ovs_bridge(NMConnection *connection); -NM_AVAILABLE_IN_1_10 +NM_AVAILABLE_IN_1_14 NMSettingOvsInterface *nm_connection_get_setting_ovs_interface(NMConnection *connection); -NMSettingOvsPatch *nm_connection_get_setting_ovs_patch(NMConnection *connection); -NM_AVAILABLE_IN_1_10 +NM_AVAILABLE_IN_1_14 +NMSettingOvsPatch *nm_connection_get_setting_ovs_patch(NMConnection *connection); +NM_AVAILABLE_IN_1_14 NMSettingOvsPort *nm_connection_get_setting_ovs_port(NMConnection *connection); NMSettingPpp *nm_connection_get_setting_ppp(NMConnection *connection); NMSettingPppoe *nm_connection_get_setting_pppoe(NMConnection *connection); @@ -234,7 +235,7 @@ NMSettingProxy *nm_connection_get_setting_proxy(NMConnection *connection); NMSettingSerial *nm_connection_get_setting_serial(NMConnection *connection); NM_AVAILABLE_IN_1_12 NMSettingTCConfig *nm_connection_get_setting_tc_config(NMConnection *connection); -NM_AVAILABLE_IN_1_2 +NM_AVAILABLE_IN_1_14 NMSettingTun *nm_connection_get_setting_tun(NMConnection *connection); NMSettingVpn *nm_connection_get_setting_vpn(NMConnection *connection); NMSettingWimax *nm_connection_get_setting_wimax(NMConnection *connection); diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h index 4557dde0..6e1a84a1 100644 --- a/src/libnm-core-public/nm-dbus-interface.h +++ b/src/libnm-core-public/nm-dbus-interface.h @@ -103,6 +103,8 @@ * The range 0x7000 - 0x7FFF of capabilities is guaranteed not to be * used by upstream NetworkManager. It could thus be used for downstream * extensions. + * + * Since: 1.6 */ typedef enum { NM_CAPABILITY_TEAM = 1, @@ -967,7 +969,7 @@ typedef enum { * * The flags for CheckpointCreate call * - * Since: 1.4 (gi flags generated since 1.12) + * Since: 1.12 (public since 1.4, g-ir since 1.12) */ typedef enum /*< flags >*/ { NM_CHECKPOINT_CREATE_FLAG_NONE = 0, diff --git a/src/libnm-core-public/nm-dbus-types.xml b/src/libnm-core-public/nm-dbus-types.xml index cb72820d..52ac4981 100644 --- a/src/libnm-core-public/nm-dbus-types.xml +++ b/src/libnm-core-public/nm-dbus-types.xml @@ -18,7 +18,7 @@ <indexterm zone="NMCapability"> <primary>NMCapability</primary> </indexterm> - <para><para><link linkend="NMCapability">NMCapability</link> names the numbers in the Capabilities property. Capabilities are positive numbers. They are part of stable API and a certain capability number is guaranteed not to change.</para><para>The range 0x7000 - 0x7FFF of capabilities is guaranteed not to be used by upstream NetworkManager. It could thus be used for downstream extensions.</para><para></para></para> + <para><para><link linkend="NMCapability">NMCapability</link> names the numbers in the Capabilities property. Capabilities are positive numbers. They are part of stable API and a certain capability number is guaranteed not to change.</para><para>The range 0x7000 - 0x7FFF of capabilities is guaranteed not to be used by upstream NetworkManager. It could thus be used for downstream extensions.</para><para>Since: 1.6</para><para></para></para> <refsect3 role="enum_members"> <title>Values</title> <informaltable role="enum_members_table" pgwide="1" frame="none"> @@ -1613,7 +1613,7 @@ <indexterm zone="NMCheckpointCreateFlags"> <primary>NMCheckpointCreateFlags</primary> </indexterm> - <para><para>The flags for CheckpointCreate call</para><para>Since: 1.4 (gi flags generated since 1.12)</para><para></para></para> + <para><para>The flags for CheckpointCreate call</para><para>Since: 1.12 (public since 1.4, g-ir since 1.12)</para><para></para></para> <refsect3 role="enum_members"> <title>Values</title> <informaltable role="enum_members_table" pgwide="1" frame="none"> diff --git a/src/libnm-core-public/nm-setting-6lowpan.h b/src/libnm-core-public/nm-setting-6lowpan.h index 358ccff6..ab2f7b44 100644 --- a/src/libnm-core-public/nm-setting-6lowpan.h +++ b/src/libnm-core-public/nm-setting-6lowpan.h @@ -33,10 +33,10 @@ typedef struct _NMSetting6LowpanClass NMSetting6LowpanClass; NM_AVAILABLE_IN_1_14 GType nm_setting_6lowpan_get_type(void); -NM_AVAILABLE_IN_1_14 +NM_AVAILABLE_IN_1_40_4 NMSetting *nm_setting_6lowpan_new(void); -NM_AVAILABLE_IN_1_14 +NM_AVAILABLE_IN_1_40_4 const char *nm_setting_6lowpan_get_parent(NMSetting6Lowpan *setting); G_END_DECLS diff --git a/src/libnm-core-public/nm-setting-connection.h b/src/libnm-core-public/nm-setting-connection.h index 4b6ce17c..4f6653bf 100644 --- a/src/libnm-core-public/nm-setting-connection.h +++ b/src/libnm-core-public/nm-setting-connection.h @@ -73,6 +73,8 @@ G_BEGIN_DECLS * * #NMSettingConnectionAutoconnectSlaves values indicate whether slave connections * should be activated when master is activated. + * + * Since: 1.2 */ typedef enum { NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT = -1, @@ -87,6 +89,8 @@ typedef enum { * @NM_SETTING_CONNECTION_LLDP_ENABLE_RX: enable reception of LLDP frames * * #NMSettingConnectionLldp values indicate whether LLDP should be enabled. + * + * Since: 1.2 */ typedef enum { NM_SETTING_CONNECTION_LLDP_DEFAULT = -1, @@ -217,7 +221,7 @@ NMSettingConnectionLlmnr nm_setting_connection_get_llmnr(NMSettingConnection *se NM_AVAILABLE_IN_1_34 NMSettingConnectionDnsOverTls nm_setting_connection_get_dns_over_tls(NMSettingConnection *setting); -NM_AVAILABLE_IN_1_40 +NM_AVAILABLE_IN_1_40_4 NMMptcpFlags nm_setting_connection_get_mptcp_flags(NMSettingConnection *setting); NM_AVAILABLE_IN_1_20 diff --git a/src/libnm-core-public/nm-setting-hostname.h b/src/libnm-core-public/nm-setting-hostname.h index f93e0efe..3fb71197 100644 --- a/src/libnm-core-public/nm-setting-hostname.h +++ b/src/libnm-core-public/nm-setting-hostname.h @@ -36,7 +36,7 @@ typedef struct _NMSettingHostnameClass NMSettingHostnameClass; NM_AVAILABLE_IN_1_30 GType nm_setting_hostname_get_type(void); -NM_AVAILABLE_IN_1_30 +NM_AVAILABLE_IN_1_40_4 NMSetting *nm_setting_hostname_new(void); NM_AVAILABLE_IN_1_30 diff --git a/src/libnm-core-public/nm-setting-ip-config.h b/src/libnm-core-public/nm-setting-ip-config.h index 6283ecc9..acbdec0f 100644 --- a/src/libnm-core-public/nm-setting-ip-config.h +++ b/src/libnm-core-public/nm-setting-ip-config.h @@ -480,7 +480,7 @@ NM_AVAILABLE_IN_1_2 int nm_setting_ip_config_get_dhcp_timeout(NMSettingIPConfig *setting); NM_AVAILABLE_IN_1_34 int nm_setting_ip_config_get_required_timeout(NMSettingIPConfig *setting); -NM_AVAILABLE_IN_1_22 +NM_AVAILABLE_IN_1_40_4 const char *nm_setting_ip_config_get_dhcp_iaid(NMSettingIPConfig *setting); NM_AVAILABLE_IN_1_22 diff --git a/src/libnm-core-public/nm-setting-ip-tunnel.h b/src/libnm-core-public/nm-setting-ip-tunnel.h index 34920099..62472f11 100644 --- a/src/libnm-core-public/nm-setting-ip-tunnel.h +++ b/src/libnm-core-public/nm-setting-ip-tunnel.h @@ -43,7 +43,7 @@ G_BEGIN_DECLS typedef struct _NMSettingIPTunnelClass NMSettingIPTunnelClass; -/* +/** * NMIPTunnelFlags: * @NM_IP_TUNNEL_FLAG_NONE: no flag * @NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT: don't add encapsulation limit @@ -94,9 +94,9 @@ NM_AVAILABLE_IN_1_2 const char *nm_setting_ip_tunnel_get_input_key(NMSettingIPTunnel *setting); NM_AVAILABLE_IN_1_2 const char *nm_setting_ip_tunnel_get_output_key(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 +NM_AVAILABLE_IN_1_40_4 guint nm_setting_ip_tunnel_get_encapsulation_limit(NMSettingIPTunnel *setting); -NM_AVAILABLE_IN_1_2 +NM_AVAILABLE_IN_1_40_4 guint nm_setting_ip_tunnel_get_flow_label(NMSettingIPTunnel *setting); NM_AVAILABLE_IN_1_2 guint nm_setting_ip_tunnel_get_mtu(NMSettingIPTunnel *setting); diff --git a/src/libnm-core-public/nm-setting-ip4-config.h b/src/libnm-core-public/nm-setting-ip4-config.h index 7991d682..66c457b9 100644 --- a/src/libnm-core-public/nm-setting-ip4-config.h +++ b/src/libnm-core-public/nm-setting-ip4-config.h @@ -113,7 +113,7 @@ const char *nm_setting_ip4_config_get_dhcp_fqdn(NMSettingIP4Config *setting); NM_AVAILABLE_IN_1_28 const char *nm_setting_ip4_config_get_dhcp_vendor_class_identifier(NMSettingIP4Config *setting); -NM_AVAILABLE_IN_1_40 +NM_AVAILABLE_IN_1_40_4 NMSettingIP4LinkLocal nm_setting_ip4_config_get_link_local(NMSettingIP4Config *setting); G_END_DECLS diff --git a/src/libnm-core-public/nm-setting-macvlan.h b/src/libnm-core-public/nm-setting-macvlan.h index 88ee81e7..25c41346 100644 --- a/src/libnm-core-public/nm-setting-macvlan.h +++ b/src/libnm-core-public/nm-setting-macvlan.h @@ -42,6 +42,8 @@ typedef struct _NMSettingMacvlanClass NMSettingMacvlanClass; * @NM_SETTING_MACVLAN_MODE_PRIVATE: private mode * @NM_SETTING_MACVLAN_MODE_PASSTHRU: passthru mode * @NM_SETTING_MACVLAN_MODE_SOURCE: source mode + * + * Since: 1.2 **/ typedef enum { NM_SETTING_MACVLAN_MODE_UNKNOWN = 0, diff --git a/src/libnm-core-public/nm-setting-ovs-bridge.h b/src/libnm-core-public/nm-setting-ovs-bridge.h index 33e8dffb..bc7d7e9b 100644 --- a/src/libnm-core-public/nm-setting-ovs-bridge.h +++ b/src/libnm-core-public/nm-setting-ovs-bridge.h @@ -49,7 +49,7 @@ NM_AVAILABLE_IN_1_10 gboolean nm_setting_ovs_bridge_get_rstp_enable(NMSettingOvsBridge *self); NM_AVAILABLE_IN_1_10 gboolean nm_setting_ovs_bridge_get_stp_enable(NMSettingOvsBridge *self); -NM_AVAILABLE_IN_1_20 +NM_AVAILABLE_IN_1_40_4 const char *nm_setting_ovs_bridge_get_datapath_type(NMSettingOvsBridge *self); G_END_DECLS diff --git a/src/libnm-core-public/nm-setting-sriov.h b/src/libnm-core-public/nm-setting-sriov.h index 93afde98..0438e800 100644 --- a/src/libnm-core-public/nm-setting-sriov.h +++ b/src/libnm-core-public/nm-setting-sriov.h @@ -109,7 +109,7 @@ NM_AVAILABLE_IN_1_14 const char **nm_sriov_vf_get_attribute_names(const NMSriovVF *vf); NM_AVAILABLE_IN_1_14 GVariant *nm_sriov_vf_get_attribute(const NMSriovVF *vf, const char *name); -NM_AVAILABLE_IN_1_14 +NM_AVAILABLE_IN_1_40_4 gboolean nm_sriov_vf_attribute_validate(const char *name, GVariant *value, gboolean *known, GError **error); diff --git a/src/libnm-core-public/nm-setting-tc-config.h b/src/libnm-core-public/nm-setting-tc-config.h index abd61683..ab1a9909 100644 --- a/src/libnm-core-public/nm-setting-tc-config.h +++ b/src/libnm-core-public/nm-setting-tc-config.h @@ -102,9 +102,9 @@ NM_AVAILABLE_IN_1_12 void nm_tc_tfilter_set_handle(NMTCTfilter *tfilter, guint32 handle); NM_AVAILABLE_IN_1_12 guint32 nm_tc_tfilter_get_parent(NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_12 +NM_AVAILABLE_IN_1_40_4 NMTCAction *nm_tc_tfilter_get_action(NMTCTfilter *tfilter); -NM_AVAILABLE_IN_1_12 +NM_AVAILABLE_IN_1_40_4 void nm_tc_tfilter_set_action(NMTCTfilter *tfilter, NMTCAction *action); #define NM_TYPE_SETTING_TC_CONFIG (nm_setting_tc_config_get_type()) diff --git a/src/libnm-core-public/nm-setting-team.h b/src/libnm-core-public/nm-setting-team.h index 63df4080..2e16ee20 100644 --- a/src/libnm-core-public/nm-setting-team.h +++ b/src/libnm-core-public/nm-setting-team.h @@ -25,6 +25,8 @@ G_BEGIN_DECLS * option 'validate_inactive' is enabled (set to true). * @NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_SEND_ALWAYS: the arp_ping link watcher option * 'send_always' is enabled (set to true). + * + * Since: 1.12 */ typedef enum /*< flags >*/ { NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE = 0, /*< skip >*/ diff --git a/src/libnm-core-public/nm-setting-tun.h b/src/libnm-core-public/nm-setting-tun.h index 8f808410..3575c644 100644 --- a/src/libnm-core-public/nm-setting-tun.h +++ b/src/libnm-core-public/nm-setting-tun.h @@ -39,6 +39,8 @@ G_BEGIN_DECLS * @NM_SETTING_TUN_MODE_TAP: a TAP device * * #NMSettingTunMode values indicate the device type (TUN/TAP) + * + * Since: 1.2 */ typedef enum { NM_SETTING_TUN_MODE_UNKNOWN = 0, diff --git a/src/libnm-core-public/nm-setting-vpn.h b/src/libnm-core-public/nm-setting-vpn.h index 151a293a..a00fa975 100644 --- a/src/libnm-core-public/nm-setting-vpn.h +++ b/src/libnm-core-public/nm-setting-vpn.h @@ -49,7 +49,9 @@ GType nm_setting_vpn_get_type(void); NMSetting *nm_setting_vpn_new(void); const char *nm_setting_vpn_get_service_type(NMSettingVpn *setting); const char *nm_setting_vpn_get_user_name(NMSettingVpn *setting); -gboolean nm_setting_vpn_get_persistent(NMSettingVpn *setting); + +NM_AVAILABLE_IN_1_40_4 +gboolean nm_setting_vpn_get_persistent(NMSettingVpn *setting); guint32 nm_setting_vpn_get_num_data_items(NMSettingVpn *setting); void nm_setting_vpn_add_data_item(NMSettingVpn *setting, const char *key, const char *item); diff --git a/src/libnm-core-public/nm-setting-wireless-security.h b/src/libnm-core-public/nm-setting-wireless-security.h index e564204b..b9fea123 100644 --- a/src/libnm-core-public/nm-setting-wireless-security.h +++ b/src/libnm-core-public/nm-setting-wireless-security.h @@ -74,6 +74,8 @@ typedef enum { * @NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED: require PMF and fail if not available * * These flags indicate whether PMF must be enabled. + * + * Since: 1.10 **/ typedef enum { NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT = 0, diff --git a/src/libnm-core-public/nm-setting-wireless.h b/src/libnm-core-public/nm-setting-wireless.h index 1f94060c..bb158112 100644 --- a/src/libnm-core-public/nm-setting-wireless.h +++ b/src/libnm-core-public/nm-setting-wireless.h @@ -132,6 +132,8 @@ typedef enum /*< flags >*/ { * @NM_SETTING_WIRELESS_POWERSAVE_ENABLE: enable powersave * * These flags indicate whether wireless powersave must be enabled. + * + * Since: 1.2 **/ typedef enum { NM_SETTING_WIRELESS_POWERSAVE_DEFAULT = 0, diff --git a/src/libnm-core-public/nm-setting-wpan.h b/src/libnm-core-public/nm-setting-wpan.h index 883b77e1..934ab196 100644 --- a/src/libnm-core-public/nm-setting-wpan.h +++ b/src/libnm-core-public/nm-setting-wpan.h @@ -38,18 +38,18 @@ typedef struct _NMSettingWpanClass NMSettingWpanClass; NM_AVAILABLE_IN_1_14 GType nm_setting_wpan_get_type(void); -NM_AVAILABLE_IN_1_14 +NM_AVAILABLE_IN_1_40_4 NMSetting *nm_setting_wpan_new(void); -NM_AVAILABLE_IN_1_14 +NM_AVAILABLE_IN_1_40_4 const char *nm_setting_wpan_get_mac_address(NMSettingWpan *setting); -NM_AVAILABLE_IN_1_14 +NM_AVAILABLE_IN_1_40_4 guint16 nm_setting_wpan_get_pan_id(NMSettingWpan *setting); -NM_AVAILABLE_IN_1_14 +NM_AVAILABLE_IN_1_40_4 guint16 nm_setting_wpan_get_short_address(NMSettingWpan *setting); -NM_AVAILABLE_IN_1_16 +NM_AVAILABLE_IN_1_40_4 gint16 nm_setting_wpan_get_page(NMSettingWpan *setting); -NM_AVAILABLE_IN_1_16 +NM_AVAILABLE_IN_1_40_4 gint16 nm_setting_wpan_get_channel(NMSettingWpan *setting); G_END_DECLS diff --git a/src/libnm-core-public/nm-setting.h b/src/libnm-core-public/nm-setting.h index ee2076c3..ae898458 100644 --- a/src/libnm-core-public/nm-setting.h +++ b/src/libnm-core-public/nm-setting.h @@ -24,15 +24,15 @@ G_BEGIN_DECLS (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING, NMSettingClass)) /* The property of the #NMSetting is required for the setting to be valid */ -#define NM_SETTING_PARAM_REQUIRED (1 << (1 + G_PARAM_USER_SHIFT)) +#define NM_SETTING_PARAM_REQUIRED 0x200 /* The property of the #NMSetting is a secret */ -#define NM_SETTING_PARAM_SECRET (1 << (2 + G_PARAM_USER_SHIFT)) +#define NM_SETTING_PARAM_SECRET 0x400 /* The property of the #NMSetting should be ignored during comparisons that * use the %NM_SETTING_COMPARE_FLAG_FUZZY flag. */ -#define NM_SETTING_PARAM_FUZZY_IGNORE (1 << (3 + G_PARAM_USER_SHIFT)) +#define NM_SETTING_PARAM_FUZZY_IGNORE 0x800 /* Note: all non-glib GParamFlags bits are reserved by NetworkManager */ @@ -122,6 +122,8 @@ typedef enum { * @NM_SETTING_MAC_RANDOMIZATION_ALWAYS: a random MAC address is used. * * Controls if and how the MAC address of a device is randomzied. + * + * Since: 1.2 **/ typedef enum { NM_SETTING_MAC_RANDOMIZATION_DEFAULT = 0, diff --git a/src/libnm-core-public/nm-utils.h b/src/libnm-core-public/nm-utils.h index 5faed75a..dc89f234 100644 --- a/src/libnm-core-public/nm-utils.h +++ b/src/libnm-core-public/nm-utils.h @@ -104,9 +104,13 @@ GPtrArray *nm_utils_ip6_addresses_from_variant(GVariant *value, char **out_gatew GVariant *nm_utils_ip6_routes_to_variant(GPtrArray *routes); GPtrArray *nm_utils_ip6_routes_from_variant(GVariant *value); -GVariant *nm_utils_ip_addresses_to_variant(GPtrArray *addresses); +NM_AVAILABLE_IN_1_40_4 +GVariant *nm_utils_ip_addresses_to_variant(GPtrArray *addresses); +NM_AVAILABLE_IN_1_40_4 GPtrArray *nm_utils_ip_addresses_from_variant(GVariant *value, int family); -GVariant *nm_utils_ip_routes_to_variant(GPtrArray *routes); +NM_AVAILABLE_IN_1_40_4 +GVariant *nm_utils_ip_routes_to_variant(GPtrArray *routes); +NM_AVAILABLE_IN_1_40_4 GPtrArray *nm_utils_ip_routes_from_variant(GVariant *value, int family); char *nm_utils_uuid_generate(void); diff --git a/src/libnm-core-public/nm-version-macros.h b/src/libnm-core-public/nm-version-macros.h index acf84ddd..04fce5df 100644 --- a/src/libnm-core-public/nm-version-macros.h +++ b/src/libnm-core-public/nm-version-macros.h @@ -30,7 +30,7 @@ * Evaluates to the micro version number of NetworkManager which this source * compiled against. */ -#define NM_MICRO_VERSION (0) +#define NM_MICRO_VERSION (6) /** * NM_CHECK_VERSION: @@ -72,6 +72,7 @@ #define NM_VERSION_1_36 (NM_ENCODE_VERSION (1, 36, 0)) #define NM_VERSION_1_38 (NM_ENCODE_VERSION (1, 38, 0)) #define NM_VERSION_1_40 (NM_ENCODE_VERSION (1, 40, 0)) +#define NM_VERSION_1_40_4 (NM_ENCODE_VERSION (1, 40, 4)) /* For releases, NM_API_VERSION is equal to NM_VERSION. * diff --git a/src/libnm-core-public/nm-version-macros.h.in b/src/libnm-core-public/nm-version-macros.h.in index 07e79899..fc854aef 100644 --- a/src/libnm-core-public/nm-version-macros.h.in +++ b/src/libnm-core-public/nm-version-macros.h.in @@ -72,6 +72,7 @@ #define NM_VERSION_1_36 (NM_ENCODE_VERSION (1, 36, 0)) #define NM_VERSION_1_38 (NM_ENCODE_VERSION (1, 38, 0)) #define NM_VERSION_1_40 (NM_ENCODE_VERSION (1, 40, 0)) +#define NM_VERSION_1_40_4 (NM_ENCODE_VERSION (1, 40, 4)) /* For releases, NM_API_VERSION is equal to NM_VERSION. * diff --git a/src/libnm-core-public/nm-version.h b/src/libnm-core-public/nm-version.h index 9f6e3e78..d9f9a121 100644 --- a/src/libnm-core-public/nm-version.h +++ b/src/libnm-core-public/nm-version.h @@ -341,6 +341,12 @@ #define NM_AVAILABLE_IN_1_40 #endif +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_40_4 +#define NM_AVAILABLE_IN_1_40_4 G_UNAVAILABLE(1, 40.4) +#else +#define NM_AVAILABLE_IN_1_40_4 +#endif + /* * Synchronous API for calling D-Bus in libnm is deprecated. See * https://networkmanager.dev/docs/libnm/latest/usage.html#sync-api diff --git a/src/libnm-core-public/nm-vpn-plugin-info.h b/src/libnm-core-public/nm-vpn-plugin-info.h index aa319a57..167af52c 100644 --- a/src/libnm-core-public/nm-vpn-plugin-info.h +++ b/src/libnm-core-public/nm-vpn-plugin-info.h @@ -62,7 +62,7 @@ NM_AVAILABLE_IN_1_4 const char *nm_vpn_plugin_info_get_auth_dialog(NMVpnPluginInfo *self); NM_AVAILABLE_IN_1_4 gboolean nm_vpn_plugin_info_supports_hints(NMVpnPluginInfo *self); -NM_AVAILABLE_IN_1_2 +NM_AVAILABLE_IN_1_40_4 gboolean nm_vpn_plugin_info_supports_multiple(NMVpnPluginInfo *self); NM_AVAILABLE_IN_1_4 const char *const *nm_vpn_plugin_info_get_aliases(NMVpnPluginInfo *self); diff --git a/src/libnm-glib-aux/nm-keyfile-aux.c b/src/libnm-glib-aux/nm-keyfile-aux.c index 1cae28b4..20a4690f 100644 --- a/src/libnm-glib-aux/nm-keyfile-aux.c +++ b/src/libnm-glib-aux/nm-keyfile-aux.c @@ -442,7 +442,7 @@ nm_key_file_db_prune(NMKeyFileDB *self, _LOGD("prune keyfile of old entries: \"%s\"", self->filename); if (!self->groups_pruned) { - /* When we prune the first time, we swap the GKeyfile instance. + /* When we prune the first time, we swap the GKeyFile instance. * The instance loaded from disk might have unrelated groups and * comments. Let's get rid of them by creating a new instance. * diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index 624f9a3e..d0885477 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -6621,19 +6621,38 @@ nm_crypto_md5_hash(const guint8 *salt, /*****************************************************************************/ -char * -nm_utils_get_process_exit_status_desc(int status) +const char * +nm_utils_get_process_exit_status_desc_buf(int status, char *buf, gsize buf_len) { + const char *buf0 = buf; + + nm_assert(buf_len == 0 || buf); + + /* This should give a partial sentence, it it can be combined with + * prinft("command XYZ %s.\n", desc) */ + if (WIFEXITED(status)) - return g_strdup_printf("exited with status %d", WEXITSTATUS(status)); + nm_strbuf_append(&buf, &buf_len, "exited with status %d", WEXITSTATUS(status)); else if (WIFSIGNALED(status)) - return g_strdup_printf("killed by signal %d", WTERMSIG(status)); + nm_strbuf_append(&buf, &buf_len, "killed by signal %d", WTERMSIG(status)); else if (WIFSTOPPED(status)) - return g_strdup_printf("stopped by signal %d", WSTOPSIG(status)); + nm_strbuf_append(&buf, &buf_len, "stopped by signal %d", WSTOPSIG(status)); else if (WIFCONTINUED(status)) - return g_strdup("resumed by SIGCONT)"); + nm_strbuf_append(&buf, &buf_len, "resumed by SIGCONT"); else - return g_strdup_printf("exited with unknown status 0x%x", status); + nm_strbuf_append(&buf, &buf_len, "exited with unknown status 0x%x", status); + + return buf0; +} + +char * +nm_utils_get_process_exit_status_desc(int status) +{ + char buf[NM_UTILS_GET_PROCESS_EXIT_STATUS_BUF_LEN]; + + nm_utils_get_process_exit_status_desc_buf(status, buf, sizeof(buf)); + + return g_strdup(buf); } /*****************************************************************************/ diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index 3d8eaced..fe7c59f3 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -809,6 +809,8 @@ gssize _nm_strv_find_first(const char *const *list, gssize len, const char *need #define nm_strv_find_first(list, len, needle) \ _nm_strv_find_first(NM_CAST_STRV_CC(list), (len), (needle)) +#define nm_strv_contains(list, len, needle) (nm_strv_find_first((list), (len), (needle)) >= 0) + gboolean nm_strv_has_duplicate(const char *const *list, gssize len, gboolean is_sorted); const char **nm_strv_cleanup_const(const char **strv, gboolean skip_empty, gboolean skip_repeated); @@ -1318,6 +1320,8 @@ typedef enum { NM_UTILS_ERROR_INVALID_ARGUMENT, /*< nick=InvalidArgument >*/ NM_UTILS_ERROR_NOT_READY, /*< nick=NotReady >*/ + NM_UTILS_ERROR_COMMAND_FAILED, /*< nick=CommandFailed >*/ + NM_UTILS_ERROR_AMBIGUOUS, /*< nick=Ambiguous >*/ /* the following codes have a special meaning and are exactly used for @@ -3403,6 +3407,10 @@ void nm_crypto_md5_hash(const guint8 *salt, /*****************************************************************************/ +#define NM_UTILS_GET_PROCESS_EXIT_STATUS_BUF_LEN 41 + +const char *nm_utils_get_process_exit_status_desc_buf(int status, char *buf, gsize buf_len); + char *nm_utils_get_process_exit_status_desc(int status); gboolean nm_utils_validate_hostname(const char *hostname); diff --git a/src/libnm-glib-aux/nm-str-buf.h b/src/libnm-glib-aux/nm-str-buf.h index 652bc96b..e8b51208 100644 --- a/src/libnm-glib-aux/nm-str-buf.h +++ b/src/libnm-glib-aux/nm-str-buf.h @@ -78,14 +78,14 @@ NM_STR_BUF_INIT(gsize allocated, gboolean do_bzero_mem) ? (size) \ : 0, \ FALSE, \ - (do_bzero_mem)); + (do_bzero_mem)) #define NM_STR_BUF_INIT_ARR(arr, do_bzero_mem) \ NM_STR_BUF_INIT_FULL((arr), \ 0, \ NM_STATIC_ASSERT_EXPR_1(sizeof(arr) > sizeof(char *)) ? sizeof(arr) : 0, \ FALSE, \ - (do_bzero_mem)); + (do_bzero_mem)) void _nm_str_buf_ensure_size(NMStrBuf *strbuf, gsize new_size, gboolean reserve_exact); @@ -530,7 +530,10 @@ nm_str_buf_finalize(NMStrBuf *strbuf, gsize *out_len) char *str = g_steal_pointer(&strbuf->_priv_str); char *result; - result = g_strndup(str, strbuf->_priv_len); + result = g_new(char, strbuf->_priv_len + 1u); + memcpy(result, str, strbuf->_priv_len); + result[strbuf->_priv_len] = '\0'; + if (strbuf->_priv_do_bzero_mem) nm_explicit_bzero(str, strbuf->_priv_len); return result; diff --git a/src/libnm-glib-aux/tests/test-shared-general.c b/src/libnm-glib-aux/tests/test-shared-general.c index 7d36d64a..cfe70b58 100644 --- a/src/libnm-glib-aux/tests/test-shared-general.c +++ b/src/libnm-glib-aux/tests/test-shared-general.c @@ -970,6 +970,16 @@ test_nm_str_buf(void) } else g_assert(stack_buf != nm_str_buf_get_str(&strbuf)); } + + { + nm_auto_str_buf NMStrBuf s1 = NM_STR_BUF_INIT_A(10, nmtst_get_rand_bool()); + gs_free char *str = NULL; + gsize l; + + nm_str_buf_append_len(&s1, "a\0b", 3); + str = nm_str_buf_finalize(&s1, &l); + g_assert_cmpmem(str, l + 1, "a\0b", 4); + } } /*****************************************************************************/ diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index cd685fe2..eb7c671b 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -1589,11 +1589,8 @@ _parse_lnk_bond(const char *kind, struct nlattr *info_data) if (tb[IFLA_BOND_MODE]) props->mode = nla_get_u8(tb[IFLA_BOND_MODE]); - if (tb[IFLA_BOND_PRIMARY]) { - props->primary = nla_get_u32(tb[IFLA_BOND_PRIMARY]); - } else if (tb[IFLA_BOND_ACTIVE_SLAVE]) { - props->primary = nla_get_u32(tb[IFLA_BOND_ACTIVE_SLAVE]); - } + if (tb[IFLA_BOND_PRIMARY]) + props->primary = NM_CLAMP((int) nla_get_u32(tb[IFLA_BOND_PRIMARY]), 0, G_MAXINT); if (tb[IFLA_BOND_MIIMON]) { props->miimon = nla_get_u32(tb[IFLA_BOND_MIIMON]); props->miimon_has = TRUE; @@ -1631,12 +1628,8 @@ _parse_lnk_bond(const char *kind, struct nlattr *info_data) } if (tb[IFLA_BOND_ARP_VALIDATE]) props->arp_validate = nla_get_u32(tb[IFLA_BOND_ARP_VALIDATE]); - if (tb[IFLA_BOND_ARP_ALL_TARGETS]) { - props->arp_all_targets = nla_get_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]); - props->arp_all_targets_has = TRUE; - } else { - props->arp_all_targets_has = FALSE; - } + if (tb[IFLA_BOND_ARP_ALL_TARGETS]) + props->arp_all_targets = nla_get_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]); if (tb[IFLA_BOND_PRIMARY_RESELECT]) props->primary_reselect = nla_get_u8(tb[IFLA_BOND_PRIMARY_RESELECT]); if (tb[IFLA_BOND_FAIL_OVER_MAC]) @@ -2677,7 +2670,7 @@ _wireguard_read_info(NMPlatform *platform /* used only as logging context */ ifindex, wireguard_family_id); - msg = nlmsg_alloc(); + msg = nlmsg_alloc(0); if (!genlmsg_put(msg, NL_AUTO_PORT, @@ -2886,7 +2879,7 @@ _wireguard_create_change_nlmsgs(NMPlatform *platfo again: - msg = nlmsg_alloc(); + msg = nlmsg_alloc(0); if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, @@ -4521,7 +4514,7 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo nla_nest_end(msg, targets); } - if (props->arp_all_targets_has) + if (props->arp_all_targets) NLA_PUT_U32(msg, IFLA_BOND_ARP_ALL_TARGETS, props->arp_all_targets); if (props->arp_interval) NLA_PUT_U32(msg, IFLA_BOND_ARP_INTERVAL, props->arp_interval); @@ -4539,7 +4532,7 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo NLA_PUT_U32(msg, IFLA_BOND_PACKETS_PER_SLAVE, props->packets_per_port); if (props->peer_notif_delay_has) NLA_PUT_U32(msg, IFLA_BOND_PEER_NOTIF_DELAY, props->peer_notif_delay); - if (props->primary) + if (props->primary > 0) NLA_PUT_U32(msg, IFLA_BOND_PRIMARY, props->primary); if (props->resend_igmp_has) NLA_PUT_U32(msg, IFLA_BOND_RESEND_IGMP, props->resend_igmp); @@ -4972,7 +4965,8 @@ _nl_msg_new_link_full(uint16_t nlmsg_type, const char *ifname, guint8 family, unsigned flags_mask, - unsigned flags_set) + unsigned flags_set, + size_t len) { nm_auto_nlmsg struct nl_msg *msg = NULL; const struct ifinfomsg ifi = { @@ -4984,7 +4978,7 @@ _nl_msg_new_link_full(uint16_t nlmsg_type, nm_assert(NM_IN_SET(nlmsg_type, RTM_DELLINK, RTM_NEWLINK, RTM_GETLINK, RTM_SETLINK)); - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); + msg = nlmsg_alloc_new(len ? nlmsg_total_size(NLMSG_HDRLEN + len) : 0, nlmsg_type, nlmsg_flags); if (nlmsg_append_struct(msg, &ifi) < 0) goto nla_put_failure; @@ -5001,7 +4995,7 @@ nla_put_failure: static struct nl_msg * _nl_msg_new_link(uint16_t nlmsg_type, uint16_t nlmsg_flags, int ifindex, const char *ifname) { - return _nl_msg_new_link_full(nlmsg_type, nlmsg_flags, ifindex, ifname, AF_UNSPEC, 0, 0); + return _nl_msg_new_link_full(nlmsg_type, nlmsg_flags, ifindex, ifname, AF_UNSPEC, 0, 0, 0); } /* Copied and modified from libnl3's build_addr_msg(). */ @@ -5033,7 +5027,7 @@ _nl_msg_new_address(uint16_t nlmsg_type, nm_assert(NM_IN_SET(family, AF_INET, AF_INET6)); nm_assert(NM_IN_SET(nlmsg_type, RTM_NEWADDR, RTM_DELADDR)); - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); + msg = nlmsg_alloc_new(0, nlmsg_type, nlmsg_flags); addr_len = family == AF_INET ? sizeof(in_addr_t) : sizeof(struct in6_addr); @@ -5140,7 +5134,7 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); nm_assert(NM_IN_SET(nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE)); - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); + msg = nlmsg_alloc_new(0, nlmsg_type, nlmsg_flags); if (nlmsg_append_struct(msg, &rtmsg) < 0) goto nla_put_failure; @@ -5232,7 +5226,7 @@ _nl_msg_new_routing_rule(uint16_t nlmsg_type, const guint8 addr_size = nm_utils_addr_family_to_size(routing_rule->addr_family); guint32 table; - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags); + msg = nlmsg_alloc_new(0, nlmsg_type, nlmsg_flags); table = routing_rule->table; @@ -5351,7 +5345,7 @@ _nl_msg_new_qdisc(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPlatformQdi .tcm_info = qdisc->info, }; - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); + msg = nlmsg_alloc_new(0, nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); if (nlmsg_append_struct(msg, &tcm) < 0) goto nla_put_failure; @@ -5439,7 +5433,7 @@ _nl_msg_new_tfilter(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPlatformT .tcm_info = tfilter->info, }; - msg = nlmsg_alloc_simple(nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); + msg = nlmsg_alloc_new(0, nlmsg_type, nlmsg_flags | NMP_NLM_FLAG_F_ECHO); if (nlmsg_append_struct(msg, &tcm) < 0) goto nla_put_failure; @@ -7234,7 +7228,7 @@ _nl_msg_new_dump_rtnl(NMPObjectType obj_type, int preferred_addr_family) nm_assert(klass); nm_assert(klass->rtm_gettype > 0); - nlmsg = nlmsg_alloc_simple(klass->rtm_gettype, NLM_F_DUMP); + nlmsg = nlmsg_alloc_new(0, klass->rtm_gettype, NLM_F_DUMP); if (klass->addr_family != AF_UNSPEC) { /* if the class specifies a particular address family, then it is preferred. */ @@ -7279,7 +7273,7 @@ _nl_msg_new_dump_genl_families(void) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - nlmsg = nlmsg_alloc_size(nlmsg_total_size(GENL_HDRLEN)); + nlmsg = nlmsg_alloc(nlmsg_total_size(GENL_HDRLEN)); if (!genlmsg_put(nlmsg, NL_AUTO_PORT, @@ -8095,7 +8089,8 @@ link_change_flags(NMPlatform *platform, int ifindex, unsigned flags_mask, unsign nm_platform_link_flags2str(flags_set, s_flags, sizeof(s_flags)), nm_platform_link_flags2str(flags_mask, s_flags2, sizeof(s_flags2))); - nlmsg = _nl_msg_new_link_full(RTM_NEWLINK, 0, ifindex, NULL, AF_UNSPEC, flags_mask, flags_set); + nlmsg = + _nl_msg_new_link_full(RTM_NEWLINK, 0, ifindex, NULL, AF_UNSPEC, flags_mask, flags_set, 0); if (!nlmsg) return -NME_UNSPEC; return do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL); @@ -8410,16 +8405,23 @@ link_set_sriov_vfs(NMPlatform *platform, int ifindex, const NMPlatformVF *const { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; struct nlattr *list, *info, *vlan_list; - guint i; + guint i = 0; + guint num = 0; + size_t buflen = 0; - nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); + while (vfs[num]) + num++; + + /* A single IFLA_VF_INFO shouldn't take more than 200 bytes. */ + buflen = (num + 1) * 200; + nlmsg = _nl_msg_new_link_full(RTM_NEWLINK, 0, ifindex, NULL, AF_UNSPEC, 0, 0, buflen); if (!nlmsg) g_return_val_if_reached(-NME_BUG); if (!(list = nla_nest_start(nlmsg, IFLA_VFINFO_LIST))) goto nla_put_failure; - for (i = 0; vfs[i]; i++) { + for (; vfs[i]; i++) { const NMPlatformVF *vf = vfs[i]; if (!(info = nla_nest_start(nlmsg, IFLA_VF_INFO))) @@ -8492,6 +8494,11 @@ link_set_sriov_vfs(NMPlatform *platform, int ifindex, const NMPlatformVF *const return (do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) >= 0); nla_put_failure: + _LOGE("error building SR-IOV VFs netlink message: used %u/%zu bytes for %u/%u VFs", + nlmsg_hdr(nlmsg)->nlmsg_len, + buflen, + i, + num); g_return_val_if_reached(FALSE); } @@ -8506,8 +8513,14 @@ link_set_bridge_vlans(NMPlatform *platform, struct bridge_vlan_info vinfo = {}; guint i; - nlmsg = - _nl_msg_new_link_full(vlans ? RTM_SETLINK : RTM_DELLINK, 0, ifindex, NULL, AF_BRIDGE, 0, 0); + nlmsg = _nl_msg_new_link_full(vlans ? RTM_SETLINK : RTM_DELLINK, + 0, + ifindex, + NULL, + AF_BRIDGE, + 0, + 0, + 0); if (!nlmsg) g_return_val_if_reached(-NME_BUG); @@ -9535,7 +9548,7 @@ tc_delete(NMPlatform *platform, log_tag = "do-delete-tc"; } - msg = nlmsg_alloc_simple(nlmsg_type, NMP_NLM_FLAG_F_ECHO); + msg = nlmsg_alloc_new(0, nlmsg_type, NMP_NLM_FLAG_F_ECHO); if (nlmsg_append_struct(msg, &tcm) < 0) goto nla_put_failure; @@ -10259,7 +10272,7 @@ mptcp_addr_update(NMPlatform *platform, NMOptionBool add, const NMPlatformMptcpA cmd_str, nm_platform_mptcp_addr_to_string(addr, sbuf, sizeof(sbuf))); - nlmsg = nlmsg_alloc_size(nlmsg_total_size(GENL_HDRLEN) + 200); + nlmsg = nlmsg_alloc(nlmsg_total_size(GENL_HDRLEN) + 200); if (!genlmsg_put(nlmsg, NL_AUTO_PORT, @@ -10350,7 +10363,7 @@ mptcp_addrs_dump(NMPlatform *platform) return NULL; } - nlmsg = nlmsg_alloc_size(nlmsg_total_size(GENL_HDRLEN)); + nlmsg = nlmsg_alloc(nlmsg_total_size(GENL_HDRLEN)); if (!genlmsg_put(nlmsg, NL_AUTO_PORT, diff --git a/src/libnm-platform/nm-netlink.c b/src/libnm-platform/nm-netlink.c index 36841d56..e08eee5e 100644 --- a/src/libnm-platform/nm-netlink.c +++ b/src/libnm-platform/nm-netlink.c @@ -364,11 +364,22 @@ nla_reserve(struct nl_msg *msg, int attrtype, int attrlen) /*****************************************************************************/ +/** + * Allocate a new netlink message. + * + * Allocates a new netlink message without any further payload. If @len is zero, + * the maximum payload size is set to the size of one memory page. + * + * @return Newly allocated netlink message or NULL. + */ struct nl_msg * -nlmsg_alloc_size(size_t len) +nlmsg_alloc(size_t len) { struct nl_msg *nm; + if (len == 0) + len = nm_utils_getpagesize(); + if (len < sizeof(struct nlmsghdr)) len = sizeof(struct nlmsghdr); else if (len > UINT32_MAX) @@ -384,38 +395,23 @@ nlmsg_alloc_size(size_t len) return nm; } -/** - * Allocate a new netlink message with the default maximum payload size. - * - * Allocates a new netlink message without any further payload. The - * maximum payload size defaults to PAGESIZE or as otherwise specified - * with nlmsg_set_default_size(). - * - * @return Newly allocated netlink message or NULL. - */ -struct nl_msg * -nlmsg_alloc(void) -{ - return nlmsg_alloc_size(nm_utils_getpagesize()); -} - struct nl_msg * nlmsg_alloc_convert(struct nlmsghdr *hdr) { struct nl_msg *nm; - nm = nlmsg_alloc_size(NLMSG_ALIGN(hdr->nlmsg_len)); + nm = nlmsg_alloc(NLMSG_ALIGN(hdr->nlmsg_len)); memcpy(nm->nm_nlh, hdr, hdr->nlmsg_len); return nm; } struct nl_msg * -nlmsg_alloc_simple(uint16_t nlmsgtype, uint16_t flags) +nlmsg_alloc_new(size_t size, uint16_t nlmsgtype, uint16_t flags) { struct nl_msg *nm; struct nlmsghdr *new; - nm = nlmsg_alloc(); + nm = nlmsg_alloc(size); new = nm->nm_nlh; new->nlmsg_type = nlmsgtype; new->nlmsg_flags = flags; @@ -928,7 +924,7 @@ genl_ctrl_resolve(struct nl_sock *sk, const char *name) .valid_arg = &response_data, }; - msg = nlmsg_alloc(); + msg = nlmsg_alloc(0); if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1)) return -ENOMEM; diff --git a/src/libnm-platform/nm-netlink.h b/src/libnm-platform/nm-netlink.h index 44ed70af..634be2b4 100644 --- a/src/libnm-platform/nm-netlink.h +++ b/src/libnm-platform/nm-netlink.h @@ -393,13 +393,11 @@ nla_parse_nested(struct nlattr *tb[], /*****************************************************************************/ -struct nl_msg *nlmsg_alloc(void); - -struct nl_msg *nlmsg_alloc_size(size_t max); +struct nl_msg *nlmsg_alloc(size_t len); struct nl_msg *nlmsg_alloc_convert(struct nlmsghdr *hdr); -struct nl_msg *nlmsg_alloc_simple(uint16_t nlmsgtype, uint16_t flags); +struct nl_msg *nlmsg_alloc_new(size_t size, uint16_t nlmsgtype, uint16_t flags); void *nlmsg_reserve(struct nl_msg *n, uint32_t len, uint32_t pad); diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index df177485..7d82083c 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -6082,7 +6082,6 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le char sbuf_updelay[30]; char sbuf_downdelay[30]; char sbuf_peer_notif_delay[60]; - char sbuf_arp_all_targets[30]; char sbuf_resend_igmp[30]; char sbuf_lp_interval[30]; char sbuf_tlb_dynamic_lb[30]; @@ -6096,7 +6095,7 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le &len, "bond" " mode %u" - " primary %u" + " primary %d" "%s" /* miimon */ "%s" /* updelay */ "%s" /* downdelay */ @@ -6106,7 +6105,7 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le "%s" /* lp_interval */ " packets_per_port %u" "%s" /* peer_notif_delay */ - "%s" /* arp_all_targets */ + " arp_all_targets %u" " arp_validate %u" " ad_actor_sys_prio %u" " ad_user_port_key %u" @@ -6156,12 +6155,7 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le !lnk->peer_notif_delay_has ? "?" : "", lnk->peer_notif_delay) : "", - lnk->arp_all_targets_has || lnk->arp_all_targets != 0 - ? nm_sprintf_buf(sbuf_arp_all_targets, - " arp_all_targets%s %u", - !lnk->arp_all_targets_has ? "?" : "", - lnk->arp_all_targets) - : "", + lnk->arp_all_targets, lnk->arp_validate, lnk->ad_actor_sys_prio, lnk->ad_user_port_key, @@ -8043,7 +8037,6 @@ nm_platform_lnk_bond_hash_update(const NMPlatformLnkBond *obj, NMHashState *h) obj->primary_reselect, obj->xmit_hash_policy, NM_HASH_COMBINE_BOOLS(guint16, - obj->arp_all_targets_has, obj->downdelay_has, obj->lp_interval_has, obj->miimon_has, @@ -8089,7 +8082,6 @@ nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b) NM_CMP_FIELD(a, b, mode); NM_CMP_FIELD(a, b, primary_reselect); NM_CMP_FIELD(a, b, xmit_hash_policy); - NM_CMP_FIELD_BOOL(a, b, arp_all_targets_has); NM_CMP_FIELD_BOOL(a, b, downdelay_has); NM_CMP_FIELD_BOOL(a, b, lp_interval_has); NM_CMP_FIELD_BOOL(a, b, miimon_has); diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index 90ffbed0..7792bbf5 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -895,6 +895,7 @@ extern const NMPlatformLnkBridge nm_platform_lnk_bridge_default; #define NM_BOND_MAX_ARP_TARGETS 16 typedef struct { + int primary; in_addr_t arp_ip_target[NM_BOND_MAX_ARP_TARGETS]; guint32 arp_all_targets; guint32 arp_interval; @@ -905,7 +906,6 @@ typedef struct { guint32 min_links; guint32 packets_per_port; guint32 peer_notif_delay; - guint32 primary; guint32 resend_igmp; guint32 updelay; guint16 ad_actor_sys_prio; @@ -920,7 +920,6 @@ typedef struct { guint8 mode; guint8 primary_reselect; guint8 xmit_hash_policy; - bool arp_all_targets_has : 1; bool downdelay_has : 1; bool lp_interval_has : 1; bool miimon_has : 1; diff --git a/src/libnm-platform/nmp-global-tracker.c b/src/libnm-platform/nmp-global-tracker.c index ea4da284..12869cb2 100644 --- a/src/libnm-platform/nmp-global-tracker.c +++ b/src/libnm-platform/nmp-global-tracker.c @@ -198,7 +198,7 @@ _track_data_hash(gconstpointer data) _track_data_assert(track_data, FALSE); nm_hash_init(&h, 269297543u); - nmp_object_id_hash_update(track_data->obj, &h); + nmp_object_hash_update(track_data->obj, &h); nm_hash_update_val(&h, track_data->user_tag); return nm_hash_complete(&h); } @@ -213,7 +213,7 @@ _track_data_equal(gconstpointer data_a, gconstpointer data_b) _track_data_assert(track_data_b, FALSE); return track_data_a->user_tag == track_data_b->user_tag - && nmp_object_id_equal(track_data_a->obj, track_data_b->obj); + && nmp_object_equal(track_data_a->obj, track_data_b->obj); } static void @@ -253,6 +253,22 @@ _track_obj_data_get_best_data(TrackObjData *obj_data) td_best = track_data; } + if (!td_best) + return NULL; + + /* Always copy the object from the best TrackData to the TrackObjData. It is + * a bit odd that this getter modifies TrackObjData. However, it gives the + * nice property that after calling _track_obj_data_get_best_data() you can + * use obj_data->obj (and get the same as td_best->obj). + * + * This is actually important, because the previous obj_data->obj will have + * the same ID, but it might have minor differences to td_best->obj. + * + * Note that at this point obj_data->obj also might be an object that is no longer + * tracked. Updating the reference will ensure that we don't have such old references + * around and update to use the most appropriate one. */ + nmp_object_ref_set(&obj_data->obj, td_best->obj); + return td_best; } diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c index d06aa9cd..6609a7d5 100644 --- a/src/libnm-platform/nmp-object.c +++ b/src/libnm-platform/nmp-object.c @@ -1318,10 +1318,9 @@ nmp_object_copy(NMPObject *dst, const NMPObject *src, gboolean id_only) g_return_if_fail(klass == NMP_OBJECT_GET_CLASS(src)); - if (id_only) { - if (klass->cmd_plobj_id_copy) - klass->cmd_plobj_id_copy(&dst->object, &src->object); - } else if (klass->cmd_obj_copy) + if (id_only && klass->cmd_plobj_id_copy) + klass->cmd_plobj_id_copy(&dst->object, &src->object); + else if (klass->cmd_obj_copy) klass->cmd_obj_copy(dst, src); else memcpy(&dst->object, &src->object, klass->sizeof_data); diff --git a/src/libnm-platform/tests/test-nm-platform.c b/src/libnm-platform/tests/test-nm-platform.c index c351f014..cd54df92 100644 --- a/src/libnm-platform/tests/test-nm-platform.c +++ b/src/libnm-platform/tests/test-nm-platform.c @@ -27,10 +27,9 @@ test_use_symbols(void) (void (*)(void)) nlmsg_hdr, (void (*)(void)) nlmsg_reserve, (void (*)(void)) nla_reserve, - (void (*)(void)) nlmsg_alloc_size, - (void (*)(void)) nlmsg_alloc, (void (*)(void)) nlmsg_alloc_convert, - (void (*)(void)) nlmsg_alloc_simple, + (void (*)(void)) nlmsg_alloc_new, + (void (*)(void)) nlmsg_alloc, (void (*)(void)) nlmsg_free, (void (*)(void)) nlmsg_append, (void (*)(void)) nlmsg_parse, diff --git a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c index 37edd928..c7ee0473 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c @@ -86,7 +86,7 @@ _nl80211_alloc_msg(guint16 genl_family_id, int ifindex, int phy, uint8_t cmd, ui { nm_auto_nlmsg struct nl_msg *msg = NULL; - msg = nlmsg_alloc(); + msg = nlmsg_alloc(0); genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, genl_family_id, 0, flags, cmd, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); if (phy != -1) diff --git a/src/libnm-platform/wpan/nm-wpan-utils.c b/src/libnm-platform/wpan/nm-wpan-utils.c index 675efe5a..03c9581f 100644 --- a/src/libnm-platform/wpan/nm-wpan-utils.c +++ b/src/libnm-platform/wpan/nm-wpan-utils.c @@ -79,7 +79,7 @@ _nl802154_alloc_msg(guint16 genl_family_id, int ifindex, uint8_t cmd, uint16_t f { nm_auto_nlmsg struct nl_msg *msg = NULL; - msg = nlmsg_alloc(); + msg = nlmsg_alloc(0); if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, genl_family_id, 0, flags, cmd, 0)) goto nla_put_failure; NLA_PUT_U32(msg, NL802154_ATTR_IFINDEX, ifindex); diff --git a/src/libnm-std-aux/nm-std-aux.h b/src/libnm-std-aux/nm-std-aux.h index 77243ab1..d49f7c43 100644 --- a/src/libnm-std-aux/nm-std-aux.h +++ b/src/libnm-std-aux/nm-std-aux.h @@ -170,8 +170,8 @@ typedef uint64_t _nm_bitwise nm_be64_t; #define NM_LIKELY(expr) (__builtin_expect(NM_BOOLEAN_EXPR(expr), 1)) #define NM_UNLIKELY(expr) (__builtin_expect(NM_BOOLEAN_EXPR(expr), 0)) #else -#define NM_LIKELY(expr) NM_BOOLEAN_EXPR(expr) -#define NM_UNLIKELY(expr) NM_BOOLEAN_EXPR(expr) +#define NM_LIKELY(expr) (NM_BOOLEAN_EXPR(expr)) +#define NM_UNLIKELY(expr) (NM_BOOLEAN_EXPR(expr)) #endif /*****************************************************************************/ diff --git a/src/libnmc-setting/settings-docs-input.xml b/src/libnmc-setting/settings-docs-input.xml index d9ce0e2d..77643955 100644 --- a/src/libnmc-setting/settings-docs-input.xml +++ b/src/libnmc-setting/settings-docs-input.xml @@ -132,9 +132,7 @@ This property is currently not implemented for DHCPv6.</description></property><property name="dhcp-send-hostname" name_upper="DHCP_SEND_HOSTNAME" type="boolean" default="TRUE"><description-docbook><para> If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the "dhcp-hostname" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.</para></description-docbook><description> If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the "dhcp-hostname" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.</description></property><property name="dhcp-timeout" name_upper="DHCP_TIMEOUT" type="int32" default="0"><description-docbook><para> A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds).</para><para> Set to 2147483647 (MAXINT32) for infinity.</para></description-docbook><description> A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). - Set to 2147483647 (MAXINT32) for infinity.</description></property><property name="dhcp-vendor-class-identifier" name_upper="DHCP_VENDOR_CLASS_IDENTIFIER" type="string"><description-docbook><para> The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server.</para><para> Since 1.28</para></description-docbook><description> The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server. - - Since 1.28</description></property><property name="dns" name_upper="DNS" type="array of uint32"><description-docbook><para> Array of IP addresses of DNS servers.</para></description-docbook><description> Array of IP addresses of DNS servers.</description></property><property name="dns-options" name_upper="DNS_OPTIONS" type="array of string"><description-docbook><para> Array of DNS options as described in man 5 resolv.conf.</para><para> NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.</para><para> The currently supported options are "attempts", "debug", "edns0", "inet6", "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", "no-ip6-dotint", "no-reload", "no-tld-query", "rotate", "single-request", "single-request-reopen", "timeout", "trust-ad", "use-vc".</para><para> The "trust-ad" setting is only honored if the profile contributes name servers to resolv.conf, and if all contributing profiles have "trust-ad" enabled.</para><para> When using a caching DNS plugin (dnsmasq or systemd-resolved in NetworkManager.conf) then "edns0" and "trust-ad" are automatically added.</para></description-docbook><description> Array of DNS options as described in man 5 resolv.conf. + Set to 2147483647 (MAXINT32) for infinity.</description></property><property name="dhcp-vendor-class-identifier" name_upper="DHCP_VENDOR_CLASS_IDENTIFIER" type="string"><description-docbook><para> The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server.</para></description-docbook><description> The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server.</description></property><property name="dns" name_upper="DNS" type="array of uint32"><description-docbook><para> Array of IP addresses of DNS servers.</para></description-docbook><description> Array of IP addresses of DNS servers.</description></property><property name="dns-options" name_upper="DNS_OPTIONS" type="array of string"><description-docbook><para> Array of DNS options as described in man 5 resolv.conf.</para><para> NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties.</para><para> The currently supported options are "attempts", "debug", "edns0", "inet6", "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", "no-ip6-dotint", "no-reload", "no-tld-query", "rotate", "single-request", "single-request-reopen", "timeout", "trust-ad", "use-vc".</para><para> The "trust-ad" setting is only honored if the profile contributes name servers to resolv.conf, and if all contributing profiles have "trust-ad" enabled.</para><para> When using a caching DNS plugin (dnsmasq or systemd-resolved in NetworkManager.conf) then "edns0" and "trust-ad" are automatically added.</para></description-docbook><description> Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties. @@ -164,11 +162,9 @@ Setting the gateway causes NetworkManager to configure a standard default route with the gateway as next hop. This is ignored if "never-default" is set. An alternative is to configure the default route explicitly with a manual route and /0 as prefix length. - Note that the gateway usually conflicts with routing that NetworkManager configures for WireGuard interfaces, so usually it should not be set in that case. See "ip4-auto-default-route".</description></property><property name="ignore-auto-dns" name_upper="IGNORE_AUTO_DNS" type="boolean" default="FALSE"><description-docbook><para> When "method" is set to "auto" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the "dns" and "dns-search" properties, if any, are used.</para></description-docbook><description> When "method" is set to "auto" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the "dns" and "dns-search" properties, if any, are used.</description></property><property name="ignore-auto-routes" name_upper="IGNORE_AUTO_ROUTES" type="boolean" default="FALSE"><description-docbook><para> When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used.</para></description-docbook><description> When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used.</description></property><property name="link-local" name_upper="LINK_LOCAL" type="int32" default="0"><description-docbook><para> Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server.</para><para> When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default".</para><para> Since 1.40</para></description-docbook><description> Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. - - When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default". + Note that the gateway usually conflicts with routing that NetworkManager configures for WireGuard interfaces, so usually it should not be set in that case. See "ip4-auto-default-route".</description></property><property name="ignore-auto-dns" name_upper="IGNORE_AUTO_DNS" type="boolean" default="FALSE"><description-docbook><para> When "method" is set to "auto" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the "dns" and "dns-search" properties, if any, are used.</para></description-docbook><description> When "method" is set to "auto" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the "dns" and "dns-search" properties, if any, are used.</description></property><property name="ignore-auto-routes" name_upper="IGNORE_AUTO_ROUTES" type="boolean" default="FALSE"><description-docbook><para> When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used.</para></description-docbook><description> When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used.</description></property><property name="link-local" name_upper="LINK_LOCAL" type="int32" default="0"><description-docbook><para> Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server.</para><para> When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default".</para></description-docbook><description> Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. - Since 1.40</description></property><property name="may-fail" name_upper="MAY_FAIL" type="boolean" default="TRUE"><description-docbook><para> If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.</para></description-docbook><description> If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.</description></property><property name="method" name_upper="METHOD" type="string"><description-docbook><para> IP configuration method.</para><para> NMSettingIP4Config and NMSettingIP6Config both support "disabled", "auto", "manual", and "link-local". See the subclass-specific documentation for other values.</para><para> In general, for the "auto" method, properties such as "dns" and "routes" specify information that is added on to the information returned from automatic configuration. The "ignore-auto-routes" and "ignore-auto-dns" properties modify this behavior.</para><para> For methods that imply no upstream network, such as "shared" or "link-local", these properties must be empty.</para><para> For IPv4 method "shared", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.</para></description-docbook><description> IP configuration method. + When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default".</description></property><property name="may-fail" name_upper="MAY_FAIL" type="boolean" default="TRUE"><description-docbook><para> If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.</para></description-docbook><description> If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.</description></property><property name="method" name_upper="METHOD" type="string"><description-docbook><para> IP configuration method.</para><para> NMSettingIP4Config and NMSettingIP6Config both support "disabled", "auto", "manual", and "link-local". See the subclass-specific documentation for other values.</para><para> In general, for the "auto" method, properties such as "dns" and "routes" specify information that is added on to the information returned from automatic configuration. The "ignore-auto-routes" and "ignore-auto-dns" properties modify this behavior.</para><para> For methods that imply no upstream network, such as "shared" or "link-local", these properties must be empty.</para><para> For IPv4 method "shared", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.</para></description-docbook><description> IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support "disabled", "auto", "manual", and "link-local". See the subclass-specific documentation for other values. diff --git a/src/libnmc-setting/settings-docs.h b/src/libnmc-setting/settings-docs.h index 1ed2f134..934ddff9 100644 --- a/src/libnmc-setting/settings-docs.h +++ b/src/libnmc-setting/settings-docs.h @@ -166,7 +166,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_REJECT_SERVERS N_("Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. \"192.168.122.0/24\"). This property is currently not implemented for DHCPv6.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.") -#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER N_("The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server. Since 1.28") +#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER N_("The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties. The currently supported options are \"attempts\", \"debug\", \"edns0\", \"inet6\", \"ip6-bytestring\", \"ip6-dotint\", \"ndots\", \"no-check-names\", \"no-ip6-dotint\", \"no-reload\", \"no-tld-query\", \"rotate\", \"single-request\", \"single-request-reopen\", \"timeout\", \"trust-ad\", \"use-vc\". The \"trust-ad\" setting is only honored if the profile contributes name servers to resolv.conf, and if all contributing profiles have \"trust-ad\" enabled. When using a caching DNS plugin (dnsmasq or systemd-resolved in NetworkManager.conf) then \"edns0\" and \"trust-ad\" are automatically added.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower numerical value is better (higher priority). Negative values have the special effect of excluding other configurations with a greater numerical priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. To avoid all DNS leaks, set the priority of the profile that should be used to the most negative value of all active connections profiles. Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. Note that commonly the resolver tries name servers in /etc/resolv.conf in the order listed, proceeding with the next server in the list on failure. See for example the \"rotate\" option of the dns-options setting. If there are any negative DNS priorities, then only name servers from the devices with that lowest priority will be considered. When using a DNS resolver that supports Conditional Forwarding or Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each connection is used to query domains in its search list. The search domains determine which name servers to ask, and the DNS priority is used to prioritize name servers based on the domain. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the best priority (lowest numerical value) wins. If a sub domain is configured on another interface it will be accepted regardless the priority, unless parent domain on the other interface has a negative priority, which causes the sub domain to be shadowed. With Split DNS one can avoid undesired DNS leaks by properly configuring DNS priorities and the search domains, so that only name servers of the desired interface are configured.") @@ -174,7 +174,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set. Setting the gateway causes NetworkManager to configure a standard default route with the gateway as next hop. This is ignored if \"never-default\" is set. An alternative is to configure the default route explicitly with a manual route and /0 as prefix length. Note that the gateway usually conflicts with routing that NetworkManager configures for WireGuard interfaces, so usually it should not be set in that case. See \"ip4-auto-default-route\".") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used.") -#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_LINK_LOCAL N_("Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to \"auto\", the value is dependent on \"ipv4.method\". When set to \"default\", it honors the global connection default, before falling back to \"auto\". Note that if \"ipv4.method\" is \"disabled\", then link local addressing is always disabled too. The default is \"default\". Since 1.40") +#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_LINK_LOCAL N_("Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to \"auto\", the value is dependent on \"ipv4.method\". When set to \"default\", it honors the global connection default, before falling back to \"auto\". Note that if \"ipv4.method\" is \"disabled\", then link local addressing is always disabled too. The default is \"default\".") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"disabled\", \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration. The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.") diff --git a/src/libnmc-setting/settings-docs.h.in b/src/libnmc-setting/settings-docs.h.in index 1ed2f134..934ddff9 100644 --- a/src/libnmc-setting/settings-docs.h.in +++ b/src/libnmc-setting/settings-docs.h.in @@ -166,7 +166,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_REJECT_SERVERS N_("Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. \"192.168.122.0/24\"). This property is currently not implemented for DHCPv6.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME N_("If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the \"dhcp-hostname\" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT N_("A timeout for a DHCP transaction in seconds. If zero (the default), a globally configured default is used. If still unspecified, a device specific timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for infinity.") -#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER N_("The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server. Since 1.28") +#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER N_("The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS N_("Array of IP addresses of DNS servers.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS N_("Array of DNS options as described in man 5 resolv.conf. NULL means that the options are unset and left at the default. In this case NetworkManager will use default options. This is distinct from an empty list of properties. The currently supported options are \"attempts\", \"debug\", \"edns0\", \"inet6\", \"ip6-bytestring\", \"ip6-dotint\", \"ndots\", \"no-check-names\", \"no-ip6-dotint\", \"no-reload\", \"no-tld-query\", \"rotate\", \"single-request\", \"single-request-reopen\", \"timeout\", \"trust-ad\", \"use-vc\". The \"trust-ad\" setting is only honored if the profile contributes name servers to resolv.conf, and if all contributing profiles have \"trust-ad\" enabled. When using a caching DNS plugin (dnsmasq or systemd-resolved in NetworkManager.conf) then \"edns0\" and \"trust-ad\" are automatically added.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY N_("DNS servers priority. The relative priority for DNS servers specified by this setting. A lower numerical value is better (higher priority). Negative values have the special effect of excluding other configurations with a greater numerical priority value; so in presence of at least one negative priority, only DNS servers from connections with the lowest priority value will be used. To avoid all DNS leaks, set the priority of the profile that should be used to the most negative value of all active connections profiles. Zero selects a globally configured default value. If the latter is missing or zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other connections. Note that the priority is to order DNS settings for multiple active connections. It does not disambiguate multiple DNS servers within the same connection profile. When multiple devices have configurations with the same priority, VPNs will be considered first, then devices with the best (lowest metric) default route and then all other devices. When using dns=default, servers with higher priority will be on top of resolv.conf. To prioritize a given server over another one within the same connection, just specify them in the desired order. Note that commonly the resolver tries name servers in /etc/resolv.conf in the order listed, proceeding with the next server in the list on failure. See for example the \"rotate\" option of the dns-options setting. If there are any negative DNS priorities, then only name servers from the devices with that lowest priority will be considered. When using a DNS resolver that supports Conditional Forwarding or Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each connection is used to query domains in its search list. The search domains determine which name servers to ask, and the DNS priority is used to prioritize name servers based on the domain. Queries for domains not present in any search list are routed through connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added manually). When multiple connections specify the same domain, the one with the best priority (lowest numerical value) wins. If a sub domain is configured on another interface it will be accepted regardless the priority, unless parent domain on the other interface has a negative priority, which causes the sub domain to be shadowed. With Split DNS one can avoid undesired DNS leaks by properly configuring DNS priorities and the search domains, so that only name servers of the desired interface are configured.") @@ -174,7 +174,7 @@ #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set. Setting the gateway causes NetworkManager to configure a standard default route with the gateway as next hop. This is ignored if \"never-default\" is set. An alternative is to configure the default route explicitly with a manual route and /0 as prefix length. Note that the gateway usually conflicts with routing that NetworkManager configures for WireGuard interfaces, so usually it should not be set in that case. See \"ip4-auto-default-route\".") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used.") -#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_LINK_LOCAL N_("Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to \"auto\", the value is dependent on \"ipv4.method\". When set to \"default\", it honors the global connection default, before falling back to \"auto\". Note that if \"ipv4.method\" is \"disabled\", then link local addressing is always disabled too. The default is \"default\". Since 1.40") +#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_LINK_LOCAL N_("Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to \"auto\", the value is dependent on \"ipv4.method\". When set to \"default\", it honors the global connection default, before falling back to \"auto\". Note that if \"ipv4.method\" is \"disabled\", then link local addressing is always disabled too. The default is \"default\".") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_METHOD N_("IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support \"disabled\", \"auto\", \"manual\", and \"link-local\". See the subclass-specific documentation for other values. In general, for the \"auto\" method, properties such as \"dns\" and \"routes\" specify information that is added on to the information returned from automatic configuration. The \"ignore-auto-routes\" and \"ignore-auto-dns\" properties modify this behavior. For methods that imply no upstream network, such as \"shared\" or \"link-local\", these properties must be empty. For IPv4 method \"shared\", the IP subnet can be configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.") #define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.") diff --git a/src/nm-initrd-generator/nm-initrd-generator.h b/src/nm-initrd-generator/nm-initrd-generator.h index 4f33ac65..0761c9bb 100644 --- a/src/nm-initrd-generator/nm-initrd-generator.h +++ b/src/nm-initrd-generator/nm-initrd-generator.h @@ -12,6 +12,9 @@ #define NMI_WAIT_DEVICE_TIMEOUT_MSEC 60000 #define NMI_IP_REQUIRED_TIMEOUT_MSEC 20000 +#define NMI_AUTOCONNECT_PRIORITY_CMDLINE -100 +#define NMI_AUTOCONNECT_PRIORITY_FIRMWARE -200 + static inline int get_ip_address_family(const char *str, gboolean with_prefix) { diff --git a/src/nm-initrd-generator/nmi-cmdline-reader.c b/src/nm-initrd-generator/nmi-cmdline-reader.c index 34b19e45..36bfdb0b 100644 --- a/src/nm-initrd-generator/nmi-cmdline-reader.c +++ b/src/nm-initrd-generator/nmi-cmdline-reader.c @@ -99,6 +99,7 @@ reader_create_connection(Reader *reader, const char *ifname, const char *mac, const char *type_name, + int autoconnect_priority, NMConnectionMultiConnect multi_connect) { NMConnection *connection; @@ -155,6 +156,8 @@ reader_create_connection(Reader *reader, multi_connect, NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, 1, + NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, + autoconnect_priority, NULL); if (nm_streq0(type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) { @@ -189,6 +192,7 @@ reader_get_default_connection(Reader *reader) NULL, NULL, NM_SETTING_WIRED_SETTING_NAME, + NMI_AUTOCONNECT_PRIORITY_CMDLINE, NM_CONNECTION_MULTI_CONNECT_MULTIPLE); nm_connection_add_setting(con, nm_setting_wired_new()); reader->default_connection = con; @@ -264,6 +268,7 @@ reader_get_connection(Reader *reader, ifname, mac, type_name, + NMI_AUTOCONNECT_PRIORITY_CMDLINE, NM_CONNECTION_MULTI_CONNECT_SINGLE); } setting = (NMSetting *) nm_connection_get_setting_connection(connection); @@ -1526,6 +1531,7 @@ nmi_cmdline_reader_parse(const char *etc_connections_dir, NULL, bootif, NM_SETTING_WIRED_SETTING_NAME, + NMI_AUTOCONNECT_PRIORITY_FIRMWARE, NM_CONNECTION_MULTI_CONNECT_SINGLE); } else { g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, bootif, NULL); diff --git a/src/nm-initrd-generator/nmi-dt-reader.c b/src/nm-initrd-generator/nmi-dt-reader.c index 554f5c4d..99fe25a2 100644 --- a/src/nm-initrd-generator/nmi-dt-reader.c +++ b/src/nm-initrd-generator/nmi-dt-reader.c @@ -248,6 +248,8 @@ nmi_dt_reader_parse(const char *sysfs_dir) NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_CONNECTION_ID, "OpenFirmware Connection", + NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, + NMI_AUTOCONNECT_PRIORITY_FIRMWARE, NULL)); s_ip4 = nm_setting_ip4_config_new(); diff --git a/src/nm-initrd-generator/nmi-ibft-reader.c b/src/nm-initrd-generator/nmi-ibft-reader.c index 5e4b1bb3..3f30e531 100644 --- a/src/nm-initrd-generator/nmi-ibft-reader.c +++ b/src/nm-initrd-generator/nmi-ibft-reader.c @@ -328,6 +328,8 @@ connection_setting_add(GHashTable *nic, id, NM_SETTING_CONNECTION_INTERFACE_NAME, NULL, + NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, + NMI_AUTOCONNECT_PRIORITY_FIRMWARE, NULL); g_free(uuid); diff --git a/src/nm-initrd-generator/tests/test-cmdline-reader.c b/src/nm-initrd-generator/tests/test-cmdline-reader.c index d7b7b3cb..977e58b9 100644 --- a/src/nm-initrd-generator/tests/test-cmdline-reader.c +++ b/src/nm-initrd-generator/tests/test-cmdline-reader.c @@ -13,6 +13,7 @@ #include <sys/socket.h> #include "libnm-core-intern/nm-core-internal.h" +#include "libnm-glib-aux/nm-uuid.h" #include "nm-initrd-generator/nm-initrd-generator.h" @@ -114,6 +115,9 @@ test_auto(void) g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); g_assert(nm_setting_connection_get_autoconnect(s_con)); + g_assert_cmpint(nm_setting_connection_get_autoconnect_priority(s_con), + ==, + NMI_AUTOCONNECT_PRIORITY_CMDLINE); s_wired = nm_connection_get_setting_wired(connection); g_assert(s_wired); @@ -174,6 +178,9 @@ test_dhcp_with_hostname(void) g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); g_assert(nm_setting_connection_get_autoconnect(s_con)); + g_assert_cmpint(nm_setting_connection_get_autoconnect_priority(s_con), + ==, + NMI_AUTOCONNECT_PRIORITY_CMDLINE); s_wired = nm_connection_get_setting_wired(connection); g_assert(s_wired); @@ -219,6 +226,9 @@ test_dhcp_with_mtu(void) g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); g_assert(nm_setting_connection_get_autoconnect(s_con)); + g_assert_cmpint(nm_setting_connection_get_autoconnect_priority(s_con), + ==, + NMI_AUTOCONNECT_PRIORITY_CMDLINE); s_wired = nm_connection_get_setting_wired(connection); g_assert(s_wired); @@ -279,6 +289,9 @@ test_dhcp_timeout(void) g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); g_assert_cmpint(nm_setting_connection_get_autoconnect_retries(s_con), ==, 1); g_assert(nm_setting_connection_get_autoconnect(s_con)); + g_assert_cmpint(nm_setting_connection_get_autoconnect_priority(s_con), + ==, + NMI_AUTOCONNECT_PRIORITY_CMDLINE); s_ip4 = nm_connection_get_setting_ip4_config(connection); g_assert(s_ip4); @@ -1652,7 +1665,11 @@ test_ibft_ip_dev(void) { const char *const *ARGV = NM_MAKE_STRV("ip=eth0:ibft"); NMSettingConnection *s_con; - gs_unref_object NMConnection *connection = NULL; + gs_unref_object NMConnection *connection = NULL; + const char *s_hwaddr = "00:53:00:ab:00:01"; + const char *s_vlanid = "666"; + const char *s_ipaddr = "2001:0db8:0000:0000:0000:0000:0000:0002"; + gs_free char *expected_uuid = NULL; connection = _parse_con(ARGV, "eth0"); @@ -1662,6 +1679,17 @@ test_ibft_ip_dev(void) ==, NM_SETTING_VLAN_SETTING_NAME); g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, NULL); + + expected_uuid = nm_uuid_generate_from_strings("ibft", + s_hwaddr, + s_vlanid ? "V" : "v", + s_vlanid ? s_vlanid : "", + s_ipaddr ? "A" : "DHCP", + s_ipaddr ? s_ipaddr : "", + NULL); + + g_assert_cmpstr(expected_uuid, ==, "16d9bd1c-e2ab-31ef-9196-860078e81a23"); + g_assert_cmpstr(nm_connection_get_uuid(connection), ==, expected_uuid); } static void diff --git a/src/nm-initrd-generator/tests/test-ibft-reader.c b/src/nm-initrd-generator/tests/test-ibft-reader.c index 55925a9a..4aa4d7f3 100644 --- a/src/nm-initrd-generator/tests/test-ibft-reader.c +++ b/src/nm-initrd-generator/tests/test-ibft-reader.c @@ -72,6 +72,9 @@ test_read_ibft_dhcp(void) g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, NULL); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); + g_assert_cmpint(nm_setting_connection_get_autoconnect_priority(s_con), + ==, + NMI_AUTOCONNECT_PRIORITY_FIRMWARE); s_wired = nm_connection_get_setting_wired(connection); g_assert(s_wired); @@ -121,6 +124,9 @@ test_read_ibft_static(void) g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, NULL); g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0); g_assert(nm_setting_connection_get_autoconnect(s_con)); + g_assert_cmpint(nm_setting_connection_get_autoconnect_priority(s_con), + ==, + NMI_AUTOCONNECT_PRIORITY_FIRMWARE); s_wired = nm_connection_get_setting_wired(connection); g_assert(s_wired); diff --git a/src/nmcli/devices.c b/src/nmcli/devices.c index 43bd3724..9b7ebce3 100644 --- a/src/nmcli/devices.c +++ b/src/nmcli/devices.c @@ -2919,6 +2919,8 @@ do_devices_monitor(const NMCCommand *cmd, NmCli *nmc, int argc, const char *cons nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return; } + if (!devices) + return; } else { /* No devices specified. Monitor all. */ devices = nm_client_get_devices(nmc->client); diff --git a/src/nmcli/generate-docs-nm-settings-nmcli.xml b/src/nmcli/generate-docs-nm-settings-nmcli.xml index 371081b0..5da5c979 100644 --- a/src/nmcli/generate-docs-nm-settings-nmcli.xml +++ b/src/nmcli/generate-docs-nm-settings-nmcli.xml @@ -699,9 +699,9 @@ <property name="dad-timeout" description="Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network. If an address conflict is detected, the activation will fail. A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or zero). A value greater than zero is a timeout in milliseconds. The property is currently implemented only for IPv4." /> <property name="dhcp-vendor-class-identifier" - description="The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server. Since 1.28" /> + description="The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server." /> <property name="link-local" - description="Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default". Since 1.40" /> + description="Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default"." /> <property name="dhcp-reject-servers" description="Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. "192.168.122.0/24"). This property is currently not implemented for DHCPv6." /> </setting> diff --git a/src/nmcli/generate-docs-nm-settings-nmcli.xml.in b/src/nmcli/generate-docs-nm-settings-nmcli.xml.in index 371081b0..5da5c979 100644 --- a/src/nmcli/generate-docs-nm-settings-nmcli.xml.in +++ b/src/nmcli/generate-docs-nm-settings-nmcli.xml.in @@ -699,9 +699,9 @@ <property name="dad-timeout" description="Timeout in milliseconds used to check for the presence of duplicate IP addresses on the network. If an address conflict is detected, the activation will fail. A zero value means that no duplicate address detection is performed, -1 means the default value (either configuration ipvx.dad-timeout override or zero). A value greater than zero is a timeout in milliseconds. The property is currently implemented only for IPv4." /> <property name="dhcp-vendor-class-identifier" - description="The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server. Since 1.28" /> + description="The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server." /> <property name="link-local" - description="Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default". Since 1.40" /> + description="Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default"." /> <property name="dhcp-reject-servers" description="Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. "192.168.122.0/24"). This property is currently not implemented for DHCPv6." /> </setting> diff --git a/src/nmcli/meson.build b/src/nmcli/meson.build index a122e2af..be625fe0 100644 --- a/src/nmcli/meson.build +++ b/src/nmcli/meson.build @@ -87,7 +87,7 @@ if enable_docs ], ) else - settings_docs_source = configure_file( + gen_metadata_nm_settings_nmcli_xml = configure_file( input: 'generate-docs-nm-settings-nmcli.xml.in', output: '@BASENAME@', configuration: configuration_data(), |